这是一个批量整理提交,包含以下主要改动: 1. 删除多处冗余的空行和未使用的导入 2. 修复文件末尾缺少换行符的问题 3. 调整部分模块的导入顺序与代码排版 4. 修复部分配置默认值与策略逻辑 5. 新增多个功能模块与辅助工具 6. 完善异常处理与日志记录 7. 修复速率限制、消息缓存、权限校验等逻辑bug 8. 废弃部分旧有API与配置项并添加警告提示
58 lines
1.8 KiB
Python
58 lines
1.8 KiB
Python
from __future__ import annotations
|
|
|
|
import asyncio
|
|
import threading
|
|
|
|
from yuxi.utils.logging_config import logger
|
|
|
|
|
|
class Watchdog:
|
|
def __init__(self, timeout_seconds: float = 30.0):
|
|
self._timeout = timeout_seconds
|
|
self._last_pong: float | None = None
|
|
self._lock = threading.Lock()
|
|
self._alert_callbacks: list = []
|
|
self._running = False
|
|
self._task: asyncio.Task | None = None
|
|
|
|
def feed(self) -> None:
|
|
with self._lock:
|
|
self._last_pong = asyncio.get_event_loop().time()
|
|
|
|
def is_alive(self) -> bool:
|
|
with self._lock:
|
|
if self._last_pong is None:
|
|
return False
|
|
elapsed = asyncio.get_event_loop().time() - self._last_pong
|
|
return elapsed < self._timeout
|
|
|
|
def on_timeout(self, callback) -> None:
|
|
self._alert_callbacks.append(callback)
|
|
|
|
async def start(self) -> None:
|
|
self._running = True
|
|
self._task = asyncio.create_task(self._run())
|
|
|
|
async def stop(self) -> None:
|
|
self._running = False
|
|
if self._task:
|
|
self._task.cancel()
|
|
try:
|
|
await self._task
|
|
except asyncio.CancelledError:
|
|
pass
|
|
|
|
async def _run(self) -> None:
|
|
while self._running:
|
|
await asyncio.sleep(max(self._timeout / 3, 1.0))
|
|
if not self.is_alive():
|
|
logger.warning(f"Watchdog: no pong for {self._timeout}s, triggering alerts")
|
|
for cb in self._alert_callbacks:
|
|
try:
|
|
if asyncio.iscoroutinefunction(cb):
|
|
await cb()
|
|
else:
|
|
cb()
|
|
except Exception:
|
|
logger.exception("Watchdog callback failed")
|