Source code for mersal.persistence.in_memory.in_memory_timeout_manager

import itertools
from collections.abc import AsyncIterator, Sequence
from contextlib import asynccontextmanager
from datetime import UTC, datetime
from functools import partial

from mersal.messages import MessageHeaders, TransportMessage
from mersal.timeouts import DueMessage, TimeoutManager

__all__ = ("InMemoryTimeoutManager",)


[docs] class InMemoryTimeoutManager(TimeoutManager): """Stores deferred messages in memory; they're lost when the process stops."""
[docs] def __init__(self) -> None: self._messages: dict[int, tuple[datetime, TransportMessage]] = {} self._ids = itertools.count()
def __len__(self) -> int: return len(self._messages) async def __call__(self) -> None: ...
[docs] async def defer(self, due_time: datetime, message: TransportMessage) -> None: self._messages[next(self._ids)] = (due_time, TransportMessage(message.body, MessageHeaders(message.headers)))
[docs] @asynccontextmanager async def get_due_messages(self) -> AsyncIterator[Sequence[DueMessage]]: now = datetime.now(UTC) due = sorted( ((due_time, _id, message) for _id, (due_time, message) in self._messages.items() if due_time <= now), key=lambda x: (x[0], x[1]), ) yield [DueMessage(message, partial(self._complete, _id)) for _, _id, message in due]
async def _complete(self, _id: int) -> None: self._messages.pop(_id, None)