Files
btc-accumulation-monitor/tests/test_job_registry.py
T

54 lines
1.6 KiB
Python

import threading
from dashboard.jobs import JobRegistry
def test_job_registry_atomically_reserves_only_one_job_per_kind(tmp_path):
registry = JobRegistry(tmp_path / "jobs.json")
barrier = threading.Barrier(10)
results = []
def reserve():
barrier.wait()
results.append(registry.reserve("refresh", details={"full": False}))
threads = [threading.Thread(target=reserve) for _ in range(10)]
for thread in threads:
thread.start()
for thread in threads:
thread.join()
reserved = [job for job in results if job is not None]
assert len(reserved) == 1
assert reserved[0]["id"]
assert reserved[0]["status"] == "queued"
assert registry.active("refresh")["id"] == reserved[0]["id"]
def test_job_registry_tracks_completion_and_result(tmp_path):
registry = JobRegistry(tmp_path / "jobs.json")
job = registry.reserve("history")
result = registry.run(job["id"], lambda: {"records": 42})
assert result == {"records": 42}
saved = registry.get(job["id"])
assert saved["status"] == "complete"
assert saved["result"] == {"records": 42}
assert saved["started_at"]
assert saved["finished_at"]
assert registry.active("history") is None
def test_job_registry_marks_abandoned_active_jobs_interrupted_on_restart(tmp_path):
path = tmp_path / "jobs.json"
first = JobRegistry(path)
job = first.reserve("refresh")
restarted = JobRegistry(path)
recovered = restarted.get(job["id"])
assert recovered["status"] == "interrupted"
assert recovered["finished_at"]
assert restarted.active("refresh") is None