from __future__ import annotations import asyncio import logging from collections import defaultdict logger = logging.getLogger(__name__) class SequentialQueue: def __init__(self): self._queues: dict[str, asyncio.Queue] = defaultdict(asyncio.Queue) self._processing: dict[str, bool] = defaultdict(lambda: False) self._lock = asyncio.Lock() async def process(self, key: str, handler, item) -> None: queue = self._queues[key] await queue.put(item) async with self._lock: if self._processing[key]: return self._processing[key] = True try: while True: entry = await queue.get() try: await handler(entry) except Exception: logger.exception("Error processing sequential item for key %s", key) if queue.empty(): break finally: async with self._lock: self._processing[key] = False def get_sequential_key(msg: dict, account_id: str) -> str: chat_id = "" group = msg.get("group") if group: chat_id = group.get("id", "") else: sender = msg.get("sender", {}) chat_id = sender.get("id", "unknown") return f"{account_id}:{chat_id}"