ForcePilot/backend/package/yuxi/channels/adapters/twitch/deduplicator.py

49 lines
1.4 KiB
Python
Raw Normal View History

from __future__ import annotations
import time
from collections import OrderedDict
from threading import Lock
class MessageDeduplicator:
TTL_SECONDS = 60.0
def __init__(self, max_size: int = 1000):
self._max_size = max_size
self._cache: OrderedDict[str, float] = OrderedDict()
self._lock = Lock()
def is_duplicate(self, message_id: str) -> bool:
now = time.monotonic()
with self._lock:
if message_id in self._cache:
ts = self._cache[message_id]
if now - ts < self.TTL_SECONDS:
return True
del self._cache[message_id]
self._cache[message_id] = now
self._cache.move_to_end(message_id)
if len(self._cache) > self._max_size:
self._cleanup_expired(now)
return False
def mark_seen(self, message_id: str) -> None:
with self._lock:
self._cache[message_id] = time.monotonic()
self._cache.move_to_end(message_id)
if len(self._cache) > self._max_size:
self._cleanup_expired(time.monotonic())
def _cleanup_expired(self, now: float) -> None:
expired = [k for k, ts in self._cache.items() if now - ts >= self.TTL_SECONDS]
for k in expired:
del self._cache[k]
def __len__(self) -> int:
with self._lock:
return len(self._cache)