from __future__ import annotations import time from collections import OrderedDict _MsgId = str class MessageDedup: def __init__(self, max_size: int = 500, ttl: int = 300): self._max_size = max_size self._ttl = ttl self._seen: OrderedDict[_MsgId, float] = OrderedDict() def is_duplicate(self, msg_id: _MsgId) -> bool: self._evict_expired() if msg_id in self._seen: self._seen.move_to_end(msg_id) return True return False def mark_seen(self, msg_id: _MsgId) -> None: self._evict_expired() self._seen[msg_id] = time.monotonic() self._seen.move_to_end(msg_id) while len(self._seen) > self._max_size: self._seen.popitem(last=False) def check_and_mark(self, msg_id: _MsgId) -> bool: if self.is_duplicate(msg_id): return True self.mark_seen(msg_id) return False def _evict_expired(self) -> None: now = time.monotonic() expired = [k for k, ts in self._seen.items() if now - ts > self._ttl] for k in expired: del self._seen[k] def clear(self) -> None: self._seen.clear() def __len__(self) -> int: self._evict_expired() return len(self._seen) dedup = MessageDedup()