""" Lightweight in-process job queue (docs/02). Adequate for single-worker dev; swap the backend for Redis/Celery at scale without changing callers. """ from __future__ import annotations import asyncio from typing import Any, Awaitable, Callable Job = Callable[..., Awaitable[Any]] class JobQueue: def __init__(self) -> None: self._q: "asyncio.Queue[tuple[Job, tuple[Any, ...]]]" = asyncio.Queue() async def enqueue(self, fn: Job, *args: Any) -> None: await self._q.put((fn, args)) async def worker(self) -> None: while True: fn, args = await self._q.get() try: await fn(*args) except Exception as e: # keep the worker alive on a failed job print("job failed:", repr(e)) finally: self._q.task_done() queue = JobQueue()