- Use
WorkerControllerto start/stop async tasks during ASGI lifespan. - Prefer
@app.lifespanto wire startup/shutdown; workers can depend on the same DI container used for WebSocket resources. - If
start()fails while creating or scheduling a worker, it closes any rejected coroutine, cancels and awaits tasks already scheduled, resets the controller and re-raises the original error. The same controller can then be started again. Rollback failures are attached to the original error as notes.
from falcon_pachinko import WorkerController, worker
controller = WorkerController()
@worker
async def broadcaster(*, conn_mgr):
async for ws in conn_mgr.connections():
await ws.send_media({"type": "ping"})
@app.lifespan
async def lifespan(app):
await controller.start(broadcaster, conn_mgr=app.ws_connection_manager)
yield
await controller.stop()
The @worker decorator is optional and marks intent only.
WorkerController.start() runs only the workers that the application passes to
it. An undecorated async function works in the same way.