Fast IAAI implementation
This commit is contained in:
167
tests/test_tasks.py
Normal file
167
tests/test_tasks.py
Normal file
@@ -0,0 +1,167 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from pathlib import Path
|
||||
from types import SimpleNamespace
|
||||
|
||||
import pytest
|
||||
|
||||
from iaai_sync_service.models import SyncRun
|
||||
from iaai_sync_service.sync_engine import SyncStats
|
||||
from iaai_sync_service.tasks import execute_keepalive_job, execute_sync_job
|
||||
|
||||
|
||||
class _ScalarResult:
|
||||
def __init__(self, value): # noqa: ANN001
|
||||
self._value = value
|
||||
|
||||
def scalar_one(self): # noqa: ANN201
|
||||
return self._value
|
||||
|
||||
|
||||
class FakeSession:
|
||||
def __init__(self, *, lock_acquired: bool) -> None:
|
||||
self.lock_acquired = lock_acquired
|
||||
self.runs: dict[int, SyncRun] = {}
|
||||
self.closed = False
|
||||
|
||||
def execute(self, stmt, params=None): # noqa: ANN001, ANN201
|
||||
sql = str(stmt)
|
||||
if "pg_try_advisory_lock" in sql:
|
||||
return _ScalarResult(self.lock_acquired)
|
||||
if "pg_advisory_unlock" in sql:
|
||||
return _ScalarResult(True)
|
||||
raise AssertionError(f"Unexpected SQL execute call: {sql}")
|
||||
|
||||
def add(self, obj) -> None: # noqa: ANN001
|
||||
if isinstance(obj, SyncRun):
|
||||
if obj.id is None:
|
||||
obj.id = len(self.runs) + 1
|
||||
self.runs[obj.id] = obj
|
||||
|
||||
def commit(self) -> None:
|
||||
return
|
||||
|
||||
def rollback(self) -> None:
|
||||
return
|
||||
|
||||
def get(self, model, run_id): # noqa: ANN001, ANN201
|
||||
assert model is SyncRun
|
||||
return self.runs.get(run_id)
|
||||
|
||||
def close(self) -> None:
|
||||
self.closed = True
|
||||
|
||||
|
||||
def _settings() -> SimpleNamespace:
|
||||
return SimpleNamespace(
|
||||
iaai_base_url="https://www.iaai.com",
|
||||
sync_runtime_config_file=Path("sync_runtime_config.json"),
|
||||
schema_bootstrap_enabled=True,
|
||||
advisory_lock_key=123,
|
||||
error_summary_max_len=2000,
|
||||
)
|
||||
|
||||
|
||||
def test_execute_sync_job_skips_when_lock_not_available(monkeypatch) -> None: # noqa: ANN001
|
||||
session = FakeSession(lock_acquired=False)
|
||||
monkeypatch.setattr("iaai_sync_service.tasks.get_settings", _settings)
|
||||
monkeypatch.setattr("iaai_sync_service.tasks.get_session", lambda: session)
|
||||
monkeypatch.setattr("iaai_sync_service.tasks.ensure_schema", lambda _session: None)
|
||||
|
||||
result = execute_sync_job()
|
||||
|
||||
assert result == {"status": "skipped_locked"}
|
||||
assert session.closed is True
|
||||
|
||||
|
||||
def test_execute_sync_job_success_writes_sync_run(monkeypatch) -> None: # noqa: ANN001
|
||||
session = FakeSession(lock_acquired=True)
|
||||
monkeypatch.setattr("iaai_sync_service.tasks.get_settings", _settings)
|
||||
monkeypatch.setattr("iaai_sync_service.tasks.get_session", lambda: session)
|
||||
monkeypatch.setattr("iaai_sync_service.tasks.ensure_schema", lambda _session: None)
|
||||
monkeypatch.setattr(
|
||||
"iaai_sync_service.tasks.run_sync_once",
|
||||
lambda **kwargs: (SyncStats(ids_fetched=5, cars_upserted=4, cars_failed=0, images_upserted=12), []),
|
||||
)
|
||||
|
||||
result = execute_sync_job()
|
||||
|
||||
assert result["status"] == "success"
|
||||
assert result["ids_fetched"] == 5
|
||||
run = session.runs[result["run_id"]]
|
||||
assert run.status == "success"
|
||||
assert run.cars_upserted == 4
|
||||
|
||||
|
||||
def test_execute_sync_job_marks_failed_when_sync_raises(monkeypatch) -> None: # noqa: ANN001
|
||||
session = FakeSession(lock_acquired=True)
|
||||
monkeypatch.setattr("iaai_sync_service.tasks.get_settings", _settings)
|
||||
monkeypatch.setattr("iaai_sync_service.tasks.get_session", lambda: session)
|
||||
monkeypatch.setattr("iaai_sync_service.tasks.ensure_schema", lambda _session: None)
|
||||
|
||||
def _raise(**kwargs): # noqa: ANN003, ANN202
|
||||
raise RuntimeError("boom")
|
||||
|
||||
monkeypatch.setattr("iaai_sync_service.tasks.run_sync_once", _raise)
|
||||
|
||||
with pytest.raises(RuntimeError, match="boom"):
|
||||
execute_sync_job()
|
||||
|
||||
failed = session.runs[1]
|
||||
assert failed.status == "failed"
|
||||
assert failed.error_summary is not None
|
||||
|
||||
|
||||
def test_execute_sync_job_skips_schema_bootstrap_when_disabled(monkeypatch) -> None: # noqa: ANN001
|
||||
session = FakeSession(lock_acquired=False)
|
||||
settings = _settings()
|
||||
settings.schema_bootstrap_enabled = False
|
||||
|
||||
monkeypatch.setattr("iaai_sync_service.tasks.get_settings", lambda: settings)
|
||||
monkeypatch.setattr("iaai_sync_service.tasks.get_session", lambda: session)
|
||||
|
||||
def _fail_if_called(_session): # noqa: ANN001, ANN202
|
||||
raise AssertionError("ensure_schema should not be called")
|
||||
|
||||
monkeypatch.setattr("iaai_sync_service.tasks.ensure_schema", _fail_if_called)
|
||||
|
||||
result = execute_sync_job()
|
||||
assert result == {"status": "skipped_locked"}
|
||||
|
||||
|
||||
def test_execute_keepalive_job_skips_when_lock_not_available(monkeypatch) -> None: # noqa: ANN001
|
||||
session = FakeSession(lock_acquired=False)
|
||||
monkeypatch.setattr("iaai_sync_service.tasks.get_settings", _settings)
|
||||
monkeypatch.setattr("iaai_sync_service.tasks.get_session", lambda: session)
|
||||
|
||||
result = execute_keepalive_job()
|
||||
|
||||
assert result == {"status": "skipped_locked"}
|
||||
assert session.closed is True
|
||||
|
||||
|
||||
def test_execute_keepalive_job_success(monkeypatch) -> None: # noqa: ANN001
|
||||
session = FakeSession(lock_acquired=True)
|
||||
monkeypatch.setattr("iaai_sync_service.tasks.get_settings", _settings)
|
||||
monkeypatch.setattr("iaai_sync_service.tasks.get_session", lambda: session)
|
||||
|
||||
class _FakeClient:
|
||||
def __init__(self, settings): # noqa: ANN001
|
||||
self._settings = settings
|
||||
|
||||
def keep_session_alive(self): # noqa: ANN201
|
||||
return {
|
||||
"scope": "https://www.iaai.com/Search?url=abc",
|
||||
"marker_present": True,
|
||||
"result_count": 1234,
|
||||
"elapsed_ms": 456,
|
||||
}
|
||||
|
||||
monkeypatch.setattr("iaai_sync_service.tasks.IAAIClient", _FakeClient)
|
||||
|
||||
result = execute_keepalive_job()
|
||||
|
||||
assert result["status"] == "success"
|
||||
assert result["marker_present"] is True
|
||||
assert result["result_count"] == 1234
|
||||
assert session.closed is True
|
||||
Reference in New Issue
Block a user