Source code for mersal.threading.anyio.anyio_periodic_async_task
from contextlib import AsyncExitStack
from dataclasses import dataclass
import anyio
from anyio import CancelScope, sleep
from mersal.logging import Logger
from mersal.threading.periodic_async_task import PeriodicAsyncTask
from mersal.types import AsyncAnyCallable
__all__ = ("AnyIOPeriodicTask",)
[docs]
@dataclass
class AnyIOPeriodicTask(PeriodicAsyncTask):
[docs]
def __init__(
self,
description: str,
task: AsyncAnyCallable,
period: float,
logger: Logger,
) -> None:
self.description = description
self.task = task
self.period = period
self.logger = logger
self._cancel_scope: CancelScope | None = None
self._exit_stack: AsyncExitStack | None = None
async def start(self) -> None:
self._exit_stack = AsyncExitStack()
task_group = anyio.create_task_group()
await self._exit_stack.enter_async_context(task_group)
self._cancel_scope = task_group.cancel_scope
_ = task_group.start_soon(self._start)
async def stop(self) -> None:
if self._cancel_scope:
self._cancel_scope.cancel()
if self._exit_stack:
await self._exit_stack.aclose()
async def _start(self) -> None:
while True:
await sleep(self.period)
try:
await self.task()
except Exception:
self.logger.exception("periodic_task.error", task=self.description)