"""TDD gate: durable worker loop run_once lifecycle. Proves a worker claims a job, invokes the registered handler, and records success/failure on the durable job — the portable core of the production worker. """ import pytest from sqlalchemy import create_engine from app.db import Base, create_session_factory from app.models.operations import Job, JobStatus from worker import run_once @pytest.fixture() def session_factory(): engine = create_engine("sqlite+pysqlite:///:memory:") Base.metadata.create_all(engine) factory = create_session_factory(engine) try: yield factory finally: engine.dispose() def _seed(session_factory, *, organization_id="org-a", operation="graph.build", result=None): session = session_factory() job = Job( organization_id=organization_id, owner_user_id="user-1", operation=operation, status=JobStatus.QUEUED, result=result, ) session.add(job) session.commit() job_id = job.id session.close() return job_id def test_run_once_processes_and_completes_job(session_factory): job_id = _seed(session_factory, result={"graph_id": "g1"}) def handler(payload, job): assert payload == {"graph_id": "g1"} return {"ok": True} session = session_factory() try: handled = run_once( session, worker_id="w-1", organization_id="org-a", **{"graph.build": handler}, ) assert handled is True session.expire_all() refreshed = session.get(Job, job_id) assert refreshed.status == JobStatus.SUCCEEDED.value assert refreshed.result == {"ok": True} finally: session.close() def test_run_once_returns_false_when_no_job(session_factory): session = session_factory() try: assert run_once(session, worker_id="w-1") is False finally: session.close() def test_run_once_marks_unhandled_job_failed(session_factory): job_id = _seed(session_factory, operation="no.handler") session = session_factory() try: handled = run_once(session, worker_id="w-1", organization_id="org-a") assert handled is True session.expire_all() refreshed = session.get(Job, job_id) assert refreshed.status == JobStatus.FAILED.value assert refreshed.error_code finally: session.close()