# Audit this Python 3.14 asyncio worker against the declared runtime. Focus on cancellation propagation, SIGTERM shutdown, task ownership, retry races, queue draining, and current asyncio techniques. Ground every high-priority finding in the supplied code and preserve exact file and line locations. Restrict runtime claims to English Python 3.14 documentation: https://docs.python.org/3.14/library/asyncio-task.html#task-cancellation, #task-groups, #asyncio.create_task, #asyncio.timeout, https://docs.python.org/3.14/library/asyncio-queue.html#asyncio.Queue.shutdown, and https://docs.python.org/3.14/library/asyncio-eventloop.html#asyncio.loop.add_signal_handler. Use the task cancellation section for cancellation-count and awaiting-cancelled-task claims. Do not use Python 3.15 pages, translated pages, generic documentation homepages, unrelated categories, or citations that do not directly support the attached claim.

**Mode:** default  
**Runtime:** Python 3.14  
**Language:** Python

## Direct answer

The shutdown deadline does not bound SIGTERM completion: _drain_for_shutdown() times out, but its TaskGroup still owns the poller and consumers and may continue waiting (lines 415-438, 515-533). Cancellation cleanup can also leave failure persistence incomplete (lines 469-474), while the delivery race cancels tasks without awaiting them (lines 380-383). Queue.shutdown(False) and explicit worker-child cancellation provide the clearest incremental fix.

## Findings

### Lease fencing is essential after cancellation or lease loss.

**Priority:** high  
**Location:** asyncio-worker.py:452-453  
**Evidence:** `completed = await self.store.complete(
                claim=claim,`

Delivery can race with lease loss, but the supplied JobStore contract does not state that complete() and fail() reject stale owner/token combinations. This is a protocol gap, not a proven vulnerability.

**Recommendation:** Require store-side compare-and-set fencing on owner, lease_token, and lease expiry for complete(), fail(), and renew(); treat false results as non-authoritative. Sources: S7.

### Cancellation cleanup can leave claims ambiguous.

**Priority:** high  
**Location:** asyncio-worker.py:460-461  
**Evidence:** `except asyncio.CancelledError:
            await self._record_failure(`

A subsequent cancellation can interrupt store.fail(), leaving no recorded outcome while the lease remains active.

**Recommendation:** Choose reliable failure recording before propagation, or explicitly fence the claim and rely on release or lease expiry. Test cancellation during store.fail(). Sources: S7.

### Race cleanup may leave short-lived orphan tasks.

**Priority:** medium  
**Location:** asyncio-worker.py:346-347  
**Evidence:** `if not task.done():
                task.cancel("race cleanup")`

Cancelled tasks are not awaited in the final cleanup path, so cancellation and exception handling can overlap the caller’s return.

**Recommendation:** Await all race tasks with gather(return_exceptions=True). Sources: S7.

### Polling adds avoidable wakeups.

**Priority:** low  
**Location:** asyncio-worker.py:400  
**Evidence:** `await asyncio.sleep(self.policy.poll_seconds)`

The poller sleeps when full or empty, and consumers periodically wake through wait_for().

**Recommendation:** Prefer event-driven wakeups where supported; otherwise measure idle wakeups and claim latency. Sources: WEB-1.

## Upgrade path

### Make shutdown deadline real.

- Stop the poller and call queue.shutdown(False).
- Drain existing items or define release/expiry behavior for queued claims.
- When the deadline expires, explicitly cancel and await the poller and consumers before TaskGroup exit. Sources: S7, WEB-1.

### Close the race cleanup gap.

- Cancel both race tasks in every exit path.
- Await both with gather(return_exceptions=True).
- Preserve the primary delivery or lease-loss exception. Sources: S7.

### Define cancellation and lease outcomes.

- Fence complete(), fail(), and renew() by owner and lease token.
- Decide whether shutdown cancellation retries or releases a claim.
- Test repeated cancellation during failure persistence. Sources: S7.

## Sources

- [S7: Python 3.14 task cancellation guidance](https://docs.python.org/3.14/library/asyncio-task.html#task-cancellation) — Python Software Foundation
- [WEB-1: Python 3.14 asyncio Queue.shutdown](https://docs.python.org/3.14/library/asyncio-queue.html#asyncio.Queue.shutdown) — docs.python.org
