US05-06: Automate Phase E End-to-End Acceptance (#76)

This commit was merged in pull request #76.
This commit is contained in:
2026-08-16 17:05:13 +02:00
parent ac9943884d
commit 3ccef58796
13 changed files with 844 additions and 161 deletions

View File

@@ -90,6 +90,26 @@ def test_cooperative_cancellation_leaves_items_resumable(sf, jobs):
assert by_state.get(ItemState.QUEUED) == 1 # "b" left resumable
def test_a_handler_that_stops_itself_releases_the_lock(sf, jobs):
"""A handler may stop without anyone cancelling the *job* — an upload batch
cancelled through its own API does exactly that. The job is still ``running``
when it raises, so it has to reach ``cancelled`` through ``cancelling``; if that
hop is skipped the transition is rejected and the lock is held forever."""
from photo_pipeline.jobs.handlers import Cancelled
def handler(item, ctx):
raise Cancelled("the work this job wraps was stopped elsewhere")
worker = Worker(sf, {"scan": handler}, "w1")
job = jobs.enqueue("scan", lock="library_write", items=["a"])
worker.run_once()
assert jobs.get(job["id"])["state"] == JobState.CANCELLED
assert jobs.progress(job["id"])["by_state"] == {ItemState.QUEUED: 1} # resumable
# The lane is free: the next job may be enqueued under the same lock.
assert jobs.enqueue("scan", lock="library_write", items=["b"])["state"] == JobState.QUEUED
def test_fencing_rejects_superseded_worker(sf, jobs):
job = jobs.enqueue("scan", items=["a"])
stale = jobs.claim(["scan"], "old")