Files
musicseerr/backend/services/genre_cover_prewarm_service.py
T
Harvey a69a26852e Cut down unnecessary logging (#48)
* Cut down unnecessary logging

* fix format etc

* fix checks

* fix tests
2026-04-14 00:02:38 +01:00

100 lines
3.6 KiB
Python

from __future__ import annotations
import asyncio
import logging
from typing import TYPE_CHECKING
from infrastructure.queue.priority_queue import RequestPriority
if TYPE_CHECKING:
from repositories.coverart_repository import CoverArtRepository
logger = logging.getLogger(__name__)
_PREWARM_INTER_ITEM_DELAY = 2.0
_MAX_CONCURRENT_PREWARMS = 3
_MAX_MBIDS_PER_RUN = 100
class GenreCoverPrewarmService:
def __init__(self, cover_repo: CoverArtRepository) -> None:
self._cover_repo = cover_repo
self._active_genres: dict[str, asyncio.Task[None]] = {}
self._global_semaphore = asyncio.Semaphore(_MAX_CONCURRENT_PREWARMS)
def schedule_prewarm(
self,
genre_name: str,
artist_mbids: list[str],
album_mbids: list[str],
) -> None:
existing = self._active_genres.get(genre_name)
if existing is not None and not existing.done():
logger.debug("Pre-warm already in progress for genre '%s', skipping", genre_name)
return
task = asyncio.create_task(
self._prewarm(genre_name, artist_mbids, album_mbids),
name=f"genre-prewarm-{genre_name}",
)
self._active_genres[genre_name] = task
from core.task_registry import TaskRegistry
try:
TaskRegistry.get_instance().register(f"genre-prewarm-{genre_name}", task)
except RuntimeError:
pass
task.add_done_callback(
lambda _t, _g=genre_name, _ref=task: (
self._active_genres.pop(_g, None)
if self._active_genres.get(_g) is _ref
else None
)
)
async def shutdown(self) -> None:
tasks = list(self._active_genres.values())
if not tasks:
return
for t in tasks:
t.cancel()
await asyncio.gather(*tasks, return_exceptions=True)
self._active_genres.clear()
async def _prewarm(
self,
genre_name: str,
artist_mbids: list[str],
album_mbids: list[str],
) -> None:
async with self._global_semaphore:
all_artist = artist_mbids[:_MAX_MBIDS_PER_RUN]
remaining = _MAX_MBIDS_PER_RUN - len(all_artist)
all_album = album_mbids[:remaining] if remaining > 0 else []
total = len(all_artist) + len(all_album)
warmed = 0
try:
for i, mbid in enumerate(all_artist):
try:
await self._cover_repo.get_artist_image(
mbid, size=250, priority=RequestPriority.BACKGROUND_SYNC
)
warmed += 1
except Exception as exc: # noqa: BLE001
logger.debug("Pre-warm artist image failed for %s: %s", mbid[:8], exc)
if i < len(all_artist) - 1 or all_album:
await asyncio.sleep(_PREWARM_INTER_ITEM_DELAY)
for i, mbid in enumerate(all_album):
try:
await self._cover_repo.get_release_group_cover(
mbid, size="250", priority=RequestPriority.BACKGROUND_SYNC
)
warmed += 1
except Exception as exc: # noqa: BLE001
logger.debug("Pre-warm album cover failed for %s: %s", mbid[:8], exc)
if i < len(all_album) - 1:
await asyncio.sleep(_PREWARM_INTER_ITEM_DELAY)
except Exception as exc: # noqa: BLE001
logger.error("Genre cover pre-warm failed for '%s': %s", genre_name, exc)