64 lines
2.0 KiB
Python
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")
|