24 lines
719 B
Python
24 lines
719 B
Python
"""Fire-and-forget asyncio tasks that are kept alive until they finish."""
|
|
from __future__ import annotations
|
|
|
|
import asyncio
|
|
import logging
|
|
|
|
log = logging.getLogger(__name__)
|
|
_BACKGROUND: set[asyncio.Task] = set()
|
|
|
|
|
|
def _done(task: asyncio.Task) -> None:
|
|
_BACKGROUND.discard(task)
|
|
if not task.cancelled() and task.exception() is not None:
|
|
# class name only: exception text may carry paths/URLs/keys
|
|
log.error("background task failed: %s", type(task.exception()).__name__)
|
|
|
|
|
|
def spawn(coro) -> asyncio.Task:
|
|
"""create_task + strong reference (the loop only keeps weak ones)."""
|
|
task = asyncio.create_task(coro)
|
|
_BACKGROUND.add(task)
|
|
task.add_done_callback(_done)
|
|
return task
|