ForcePilot/backend/package/yuxi/channels/sdk/dedupe.py

48 lines
1.4 KiB
Python
Raw Normal View History

from __future__ import annotations
import threading
import time
from collections import OrderedDict
from dataclasses import dataclass
@dataclass
class DedupeConfig:
ttl_seconds: float = 300.0
max_entries: int = 10000
class MessageDeduplicator:
def __init__(self, config: DedupeConfig | None = None):
self._config = config or DedupeConfig()
self._cache: OrderedDict[str, float] = OrderedDict()
self._lock = threading.Lock()
def is_duplicate(self, message_id: str) -> bool:
now = time.monotonic()
with self._lock:
self._evict_expired(now)
if message_id in self._cache:
return True
if len(self._cache) >= self._config.max_entries:
self._cache.popitem(last=False)
self._cache[message_id] = now
self._cache.move_to_end(message_id)
return False
def record(self, message_id: str) -> None:
now = time.monotonic()
with self._lock:
self._evict_expired(now)
self._cache[message_id] = now
self._cache.move_to_end(message_id)
def clear(self) -> None:
with self._lock:
self._cache.clear()
def _evict_expired(self, now: float) -> None:
expired = [k for k, t in self._cache.items() if now - t > self._config.ttl_seconds]
for k in expired:
del self._cache[k]