Files
musicseerr/backend/api/v1/routes/cache_status.py
T
2026-04-03 15:53:00 +01:00

84 lines
2.9 KiB
Python

import asyncio
import logging
from fastapi import APIRouter, Depends
from fastapi.responses import StreamingResponse
import msgspec
from api.v1.schemas.cache_status import CacheSyncStatus
from core.dependencies import get_cache_status_service
from infrastructure.msgspec_fastapi import MsgSpecRoute
from services.cache_status_service import CacheStatusService
logger = logging.getLogger(__name__)
router = APIRouter(route_class=MsgSpecRoute, prefix="/cache/sync", tags=["cache"])
@router.get("/status", response_model=CacheSyncStatus)
async def get_sync_status(
status_service: CacheStatusService = Depends(get_cache_status_service),
):
progress = status_service.get_progress()
return CacheSyncStatus(
is_syncing=progress.is_syncing,
phase=progress.phase,
total_items=progress.total_items,
processed_items=progress.processed_items,
progress_percent=progress.progress_percent,
current_item=progress.current_item,
started_at=progress.started_at,
error_message=progress.error_message,
total_artists=progress.total_artists,
processed_artists=progress.processed_artists,
total_albums=progress.total_albums,
processed_albums=progress.processed_albums
)
@router.get("/stream")
async def stream_sync_status(
status_service: CacheStatusService = Depends(get_cache_status_service),
):
queue = status_service.subscribe_sse()
async def event_generator():
try:
progress = status_service.get_progress()
initial_data = {
'is_syncing': progress.is_syncing,
'phase': progress.phase,
'total_items': progress.total_items,
'processed_items': progress.processed_items,
'progress_percent': progress.progress_percent,
'current_item': progress.current_item,
'started_at': progress.started_at,
'error_message': progress.error_message,
'total_artists': progress.total_artists,
'processed_artists': progress.processed_artists,
'total_albums': progress.total_albums,
'processed_albums': progress.processed_albums
}
yield f"data: {msgspec.json.encode(initial_data).decode('utf-8')}\n\n"
while True:
try:
data = await asyncio.wait_for(queue.get(), timeout=30.0)
yield f"data: {data}\n\n"
except asyncio.TimeoutError:
yield ": keepalive\n\n"
except asyncio.CancelledError:
pass
finally:
status_service.unsubscribe_sse(queue)
return StreamingResponse(
event_generator(),
media_type="text/event-stream",
headers={
"Cache-Control": "no-cache",
"Connection": "keep-alive",
"X-Accel-Buffering": "no"
}
)