ForcePilot/backend/package/yuxi/channel/message/media_cleaner.py

64 lines
2.0 KiB
Python
Raw Normal View History

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")