from __future__ import annotations import time from collections import OrderedDict class LineEventDeduplicator: def __init__(self, max_size: int = 4096, ttl_seconds: int = 600): self._cache: OrderedDict[str, float] = OrderedDict() self._max_size = max_size self._ttl = ttl_seconds def is_duplicate(self, event_key: str) -> bool: if not event_key: return False now = time.monotonic() self._evict_expired(now) if event_key in self._cache: return True self._cache[event_key] = now while len(self._cache) > self._max_size: self._cache.popitem(last=False) return False def _evict_expired(self, now: float) -> None: expired = [k for k, v in self._cache.items() if now - v > self._ttl] for k in expired: del self._cache[k] def reset(self) -> None: self._cache.clear() def build_event_dedupe_key(account_id: str, event: dict) -> str: msg = event.get("message", {}) msg_id = msg.get("id") if msg_id: return f"{account_id}|message:{msg_id}" event_type = event.get("type", "unknown") source = event.get("source", {}) source_type = source.get("type", "") source_id = source.get("userId") or source.get("groupId") or source.get("roomId") or "" webhook_event_id = event.get("webhookEventId", "") return f"{account_id}|{event_type}|{source_type}:{source_id}|{webhook_event_id}"