From 09a0d7e682712c06174d76e001f6ab2aa1928f57 Mon Sep 17 00:00:00 2001 From: zebra Date: Mon, 8 Jun 2026 19:59:31 -0700 Subject: [PATCH] fix(server): harden job eviction and worker against missing job id Co-Authored-By: Claude Opus 4.8 --- server/jobs.py | 5 ++++- tests/test_jobs.py | 12 ++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/server/jobs.py b/server/jobs.py index 9122960..617ced8 100644 --- a/server/jobs.py +++ b/server/jobs.py @@ -30,6 +30,7 @@ def _touch(job: "Job", **changes): def _evict_if_needed(): + # Post-condition: len(JOBS) <= _MAX_JOBS (evicts oldest overflow entries). if len(JOBS) <= _MAX_JOBS: return for jid in sorted(JOBS, key=lambda j: JOBS[j].created_at)[: len(JOBS) - _MAX_JOBS]: @@ -50,7 +51,9 @@ def get_job(job_id: str) -> Optional["Job"]: def run_job(job_id: str, fn: Callable[[], dict], done_message: str, fail_message: str = "Something went wrong while fetching.") -> None: def _task(): - job = JOBS[job_id] + job = JOBS.get(job_id) + if job is None: + return _touch(job, status="running") try: result = fn() diff --git a/tests/test_jobs.py b/tests/test_jobs.py index e44d900..74a7914 100644 --- a/tests/test_jobs.py +++ b/tests/test_jobs.py @@ -41,3 +41,15 @@ def test_run_job_failure_sets_failed(): def test_get_unknown_job_returns_none(): assert jobs.get_job("nope") is None + + +def test_eviction_keeps_within_cap(): + jobs.JOBS.clear() + for i in range(jobs._MAX_JOBS + 25): + jobs.create_job(hit={"i": i}, message="m") + assert len(jobs.JOBS) <= jobs._MAX_JOBS + jobs.JOBS.clear() + + +def teardown_module(): + jobs.JOBS.clear()