ForcePilot/backend/package/yuxi/channel/message/media_cleaner.py
Kris 0b19470c70 feat(channel/message): 新增消息处理核心模块及相关工具类
本次提交新增了渠道消息处理的完整核心模块,包含以下核心功能:
1.  新增会话围栏类,实现会话并发控制与过期清理
2.  新增媒体清理器,实现过期媒体文件自动清理
3.  新增熔断器组件,实现服务降级与故障隔离
4.  新增消息处理器,完成渠道消息的完整流转处理
5.  新增限流器组件,实现渠道级和账户级流量控制
6.  新增链路追踪模块,集成Langfuse实现调用链路监控
7.  新增指标统计模块,实现消息处理全链路指标采集
8.  新增统一消息模型,封装全渠道消息格式
9.  新增块回复流水线,实现流式回复的合并与去重
10. 新增本地媒体存储模块,实现媒体文件的本地管理
11. 新增回复分发器,实现回复内容的有序发送与延迟处理
12. 完善__init__.py导出所有核心模块与工具类
2026-05-21 10:27:16 +08:00

64 lines
2.0 KiB
Python

from __future__ import annotations
import asyncio
import logging
from yuxi.channel.message.media_store import MediaStore
logger = logging.getLogger(__name__)
class MediaCleaner:
def __init__(self, media_store: MediaStore, interval_seconds: int):
self._media_store = media_store
self._interval = interval_seconds
self._task: asyncio.Task | None = None
self._stop_event = asyncio.Event()
@property
def is_running(self) -> bool:
return self._task is not None and not self._task.done()
async def start(self) -> None:
if self.is_running:
return
self._stop_event.clear()
self._task = asyncio.create_task(self._loop(), name="media-cleaner")
logger.info(
"MediaCleaner started (interval=%ds, ttl=%ds)",
self._interval,
self._media_store.ttl_seconds,
)
async def stop(self) -> None:
if not self.is_running:
return
self._stop_event.set()
try:
await asyncio.wait_for(self._task, timeout=10)
except TimeoutError:
logger.warning("MediaCleaner stop timed out, cancelling task")
self._task.cancel()
except asyncio.CancelledError:
pass
self._task = None
logger.info("MediaCleaner stopped")
async def cleanup_once(self) -> int:
return await self._media_store.cleanup_expired()
async def _loop(self) -> None:
while not self._stop_event.is_set():
try:
await asyncio.wait_for(self._stop_event.wait(), timeout=self._interval)
break
except TimeoutError:
pass
try:
deleted = await self._media_store.cleanup_expired()
if deleted:
logger.info("MediaCleaner cycle: deleted %d expired files", deleted)
except Exception:
logger.exception("MediaCleaner cycle error")