ForcePilot/backend/package/yuxi/channel/extensions/dingtalk/dedupe.py

51 lines
1.4 KiB
Python
Raw Normal View History

from __future__ import annotations
import time
from collections import OrderedDict
DEFAULT_TTL = 3600
class ExpiredDict:
def __init__(self, ttl: int = DEFAULT_TTL):
self._ttl = ttl
self._data: OrderedDict[str, tuple[object, float]] = OrderedDict()
def __contains__(self, key: str) -> bool:
self._cleanup_expired()
return key in self._data
def add(self, key: str, value: object = True) -> None:
self._cleanup_expired()
self._data[key] = (value, time.time() + self._ttl)
self._data.move_to_end(key)
def _cleanup_expired(self) -> None:
now = time.time()
while self._data:
_, (_, expires) = next(iter(self._data.items()))
if expires > now:
break
self._data.popitem(last=False)
class DingTalkDeduplicator:
def __init__(self, ttl: int = DEFAULT_TTL, hot_reload: bool = False):
self._received = ExpiredDict(ttl)
self._hot_reload = hot_reload
self._start_time = time.time()
def is_duplicate(self, msg_id: str, create_time: float | None = None) -> bool:
if msg_id in self._received:
return True
if self._hot_reload and create_time:
if create_time < self._start_time - 60:
return True
self._received.add(msg_id)
return False
def is_my_msg(self, msg) -> bool:
return getattr(msg, "my_msg", False)