"""Shared ActivityDefinition/event type/schedule sync orchestration.""" from __future__ import annotations from typing import Any from temporalio.client import Client from activity_core.event_type_registry import sync_event_types from activity_core.sync_activity_definitions import sync as sync_activity_definitions from activity_core.sync_schedules import ScheduleSyncResult, sync_with_session_factory _MAX_ERRORS = 20 _MAX_ERROR_MESSAGE_LENGTH = 1000 def _empty_result( *, definitions: bool, schedules: bool, event_types: bool, ) -> dict[str, Any]: return { "ok": True, "ran": { "definitions": definitions, "schedules": schedules, "event_types": event_types, }, "definitions": {"synced": 0}, "event_types": {"synced": 0}, "schedules": ScheduleSyncResult().to_dict(), "errors": [], } def _record_error(result: dict[str, Any], stage: str, exc: Exception) -> None: errors = result["errors"] if len(errors) >= _MAX_ERRORS: return errors.append( { "stage": stage, "type": type(exc).__name__, "message": str(exc)[:_MAX_ERROR_MESSAGE_LENGTH], } ) result["ok"] = False async def run_sync( *, session_factory: Any, temporal_client: Client | None, definitions: bool = True, schedules: bool = True, event_types: bool = False, ) -> dict[str, Any]: """Run the requested sync stages and return bounded operator-facing status. The orchestration deliberately accepts its database and Temporal dependencies as arguments so startup and the API can share the same behavior without creating another global runtime. """ result = _empty_result( definitions=definitions, schedules=schedules, event_types=event_types, ) if definitions: try: result["definitions"]["synced"] = await sync_activity_definitions( session_factory ) except Exception as exc: # pragma: no cover - exercised through tests _record_error(result, "definitions", exc) if event_types: try: result["event_types"]["synced"] = await sync_event_types(session_factory) except Exception as exc: # pragma: no cover - exercised through tests _record_error(result, "event_types", exc) if schedules: try: if temporal_client is None: raise RuntimeError("Temporal client is required for schedule sync") schedule_result = await sync_with_session_factory( temporal_client, session_factory, ) result["schedules"] = schedule_result.to_dict() except Exception as exc: # pragma: no cover - exercised through tests _record_error(result, "schedules", exc) return result