Both the single-run path and the campaign scheduler drove long-lived asyncio tasks through their own duplicated _tasks/_cancel_events dicts and shutdown loops. Collapse them into one deep TaskRegistry module, instantiated as run_registry and campaign_registry. launch() creates the cancel event before the task (so a cancel during startup is never lost), wires done-callback cleanup, and is idempotent per id; this makes runs.py's hard-cancel fallback provably dead, so it is removed. App shutdown now gracefully stops in-flight runs too, not just campaigns. |
||
|---|---|---|
| .. | ||
| routers | ||
| __init__.py | ||
| app.py | ||
| deps.py | ||
| file_schemas.py | ||
| model_config_schemas.py | ||
| websocket.py | ||