Avoid repeated artwork miss fetches and refresh churn
Lowers CPU usage: - Only call refresh() when real artwork is found - Treating NoArtwork as a valid cached result (art is not None check). - Adding in-flight dedupe (pending_tracks) so the same track doesn't spawn parallel fetches.
This commit is contained in:
parent
9b910cd991
commit
fa82f45ef9
1 changed files with 25 additions and 10 deletions
|
|
@ -30,19 +30,28 @@ class MpdArtworkCache:
|
|||
mpd: MpdStateHandler
|
||||
album_cache: Cache[Artwork]
|
||||
track_cache: Cache[Artwork]
|
||||
pending_tracks: set[str]
|
||||
|
||||
def __init__(self, mpd: MpdStateHandler, cache_url: URL = MEMORY):
|
||||
self.mpd = mpd
|
||||
self.album_cache = make_cache(ArtworkSchema, cache_url, "album")
|
||||
self.track_cache = make_cache(ArtworkSchema, cache_url, "track")
|
||||
self.pending_tracks = set()
|
||||
|
||||
async def get_cached_artwork(self, song: CurrentSongResponse) -> bytes | None:
|
||||
art = await self.track_cache.get(calc_track_key(song))
|
||||
if art:
|
||||
return art.data
|
||||
track_key = calc_track_key(song)
|
||||
art = await self.track_cache.get(track_key)
|
||||
if art is not None:
|
||||
# NoArtwork is a valid cached value too: returning None here avoids
|
||||
# repeatedly re-querying MPD for files that have no embedded art.
|
||||
if art:
|
||||
return art.data
|
||||
return None
|
||||
|
||||
# If we don't have track artwork cached, go find some.
|
||||
run_background_task(self.cache_artwork(song))
|
||||
if track_key not in self.pending_tracks:
|
||||
self.pending_tracks.add(track_key)
|
||||
run_background_task(self.cache_artwork(song))
|
||||
|
||||
# Even if we don't have cached track art, we can try looking for cached album art.
|
||||
art = await self.album_cache.get(calc_album_key(song))
|
||||
|
|
@ -52,10 +61,16 @@ class MpdArtworkCache:
|
|||
return None
|
||||
|
||||
async def cache_artwork(self, song: CurrentSongResponse) -> None:
|
||||
art = to_artwork(await self.mpd.get_art(song["file"]))
|
||||
track_key = calc_track_key(song)
|
||||
try:
|
||||
await self.album_cache.add(calc_album_key(song), art, ttl=CACHE_TTL)
|
||||
except ValueError:
|
||||
pass
|
||||
await self.track_cache.set(calc_track_key(song), art, ttl=CACHE_TTL)
|
||||
await self.mpd.refresh()
|
||||
art = to_artwork(await self.mpd.get_art(song["file"]))
|
||||
try:
|
||||
await self.album_cache.add(calc_album_key(song), art, ttl=CACHE_TTL)
|
||||
except ValueError:
|
||||
pass
|
||||
await self.track_cache.set(track_key, art, ttl=CACHE_TTL)
|
||||
# Refresh receivers only when we discovered actual artwork.
|
||||
if art:
|
||||
await self.mpd.refresh()
|
||||
finally:
|
||||
self.pending_tracks.discard(track_key)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue