generated from coulomb/repo-seed
135 lines
3.8 KiB
Python
135 lines
3.8 KiB
Python
from __future__ import annotations
|
|
|
|
from typing import Any
|
|
|
|
import pytest
|
|
|
|
from activity_core import sync_service
|
|
from activity_core.sync_schedules import ScheduleSyncResult
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_run_sync_runs_requested_sections(monkeypatch) -> None:
|
|
calls: list[str] = []
|
|
|
|
async def fake_definitions(session_factory: object) -> int:
|
|
calls.append("definitions")
|
|
return 2
|
|
|
|
async def fake_event_types(session_factory: object) -> int:
|
|
calls.append("event_types")
|
|
return 5
|
|
|
|
async def fake_schedules(
|
|
temporal_client: object,
|
|
session_factory: object,
|
|
) -> ScheduleSyncResult:
|
|
calls.append("schedules")
|
|
return ScheduleSyncResult(upserted=3, paused=1, deleted_orphans=2)
|
|
|
|
monkeypatch.setattr(sync_service, "sync_activity_definitions", fake_definitions)
|
|
monkeypatch.setattr(sync_service, "sync_event_types", fake_event_types)
|
|
monkeypatch.setattr(sync_service, "sync_with_session_factory", fake_schedules)
|
|
|
|
result = await sync_service.run_sync(
|
|
session_factory=object(),
|
|
temporal_client=object(),
|
|
definitions=True,
|
|
schedules=True,
|
|
event_types=True,
|
|
)
|
|
|
|
assert calls == ["definitions", "event_types", "schedules"]
|
|
assert result["ok"] is True
|
|
assert result["ran"] == {
|
|
"definitions": True,
|
|
"schedules": True,
|
|
"event_types": True,
|
|
}
|
|
assert result["definitions"] == {"synced": 2}
|
|
assert result["event_types"] == {"synced": 5}
|
|
assert result["schedules"] == {
|
|
"upserted": 3,
|
|
"paused": 1,
|
|
"deleted_orphans": 2,
|
|
}
|
|
assert result["errors"] == []
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_run_sync_collects_errors_and_continues(monkeypatch) -> None:
|
|
calls: list[str] = []
|
|
|
|
async def failing_definitions(session_factory: object) -> int:
|
|
calls.append("definitions")
|
|
raise RuntimeError("definition parse failed")
|
|
|
|
async def fake_schedules(
|
|
temporal_client: object,
|
|
session_factory: object,
|
|
) -> ScheduleSyncResult:
|
|
calls.append("schedules")
|
|
return ScheduleSyncResult(upserted=1)
|
|
|
|
monkeypatch.setattr(
|
|
sync_service,
|
|
"sync_activity_definitions",
|
|
failing_definitions,
|
|
)
|
|
monkeypatch.setattr(sync_service, "sync_with_session_factory", fake_schedules)
|
|
|
|
result = await sync_service.run_sync(
|
|
session_factory=object(),
|
|
temporal_client=object(),
|
|
definitions=True,
|
|
schedules=True,
|
|
event_types=False,
|
|
)
|
|
|
|
assert calls == ["definitions", "schedules"]
|
|
assert result["ok"] is False
|
|
assert result["definitions"] == {"synced": 0}
|
|
assert result["schedules"]["upserted"] == 1
|
|
assert result["errors"] == [
|
|
{
|
|
"stage": "definitions",
|
|
"type": "RuntimeError",
|
|
"message": "definition parse failed",
|
|
}
|
|
]
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_run_sync_reports_missing_temporal_client_for_schedules() -> None:
|
|
result = await sync_service.run_sync(
|
|
session_factory=object(),
|
|
temporal_client=None,
|
|
definitions=False,
|
|
schedules=True,
|
|
event_types=False,
|
|
)
|
|
|
|
assert result["ok"] is False
|
|
assert result["errors"] == [
|
|
{
|
|
"stage": "schedules",
|
|
"type": "RuntimeError",
|
|
"message": "Temporal client is required for schedule sync",
|
|
}
|
|
]
|
|
|
|
|
|
def test_record_error_bounds_error_count() -> None:
|
|
result: dict[str, Any] = {
|
|
"ok": True,
|
|
"errors": [],
|
|
}
|
|
|
|
for i in range(25):
|
|
sync_service._record_error(result, "stage", RuntimeError(f"boom {i}"))
|
|
|
|
assert result["ok"] is False
|
|
assert len(result["errors"]) == 20
|
|
assert result["errors"][0]["message"] == "boom 0"
|
|
assert result["errors"][-1]["message"] == "boom 19"
|