generated from coulomb/repo-seed
98 lines
2.9 KiB
Python
98 lines
2.9 KiB
Python
"""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
|