32 lines
861 B
Python
32 lines
861 B
Python
"""
|
|
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()
|