Avoid fetching covers via MPD if it definitely does not have them

This commit is contained in:
2026-03-22 12:21:48 +00:00
parent d1a1f9bca5
commit ba413ec03b
2 changed files with 33 additions and 7 deletions

View File

@@ -869,6 +869,31 @@ pub fn albums_without_cover(conn: &Connection) -> Result<Vec<UncachedAlbum>> {
rows.collect()
}
/// Like [`albums_without_cover`] but restricted to albums where at least one
/// scrobble came from MPD (`source = 'MPD'`).
///
/// There is no point asking MPD for a cover art of an album that was scrobbled
/// entirely via an MPRIS player (e.g. Qobuz, Spotify) — MPD almost certainly
/// does not have that file on disk. This query avoids those wasted round-trips.
pub fn albums_without_cover_from_mpd(conn: &Connection) -> Result<Vec<UncachedAlbum>> {
let mut stmt = conn.prepare(
"SELECT DISTINCT s.artist, s.album
FROM scrobbles s
LEFT JOIN album_cache c ON s.artist = c.artist AND s.album = c.album
WHERE s.album != ''
AND s.source = 'MPD'
AND (c.id IS NULL OR c.cover_url IS NULL)
ORDER BY s.artist, s.album",
)?;
let rows = stmt.query_map([], |row| {
Ok(UncachedAlbum {
artist: row.get(0)?,
album: row.get(1)?,
})
})?;
rows.collect()
}
/// Cached album metadata returned by [`album_cache_meta`].
#[derive(Debug, Clone)]
pub struct AlbumCacheMeta {

View File

@@ -942,9 +942,10 @@ fn try_extract_cover(
/// one; if it finds nothing, the local cover is preserved (see
/// `db::upsert_album_cache` for the `COALESCE` logic).
pub fn run_mpd_cover_enrich(config: &MpdConfig, conn: &Connection) {
// Fetch covers for every scrobbled album that still has no cover_url.
// Used by the standalone `enrich` command where the scope is the whole DB.
let albums = match db::albums_without_cover(conn) {
// Only consider albums where at least one scrobble came from MPD — albums
// scrobbled exclusively via MPRIS players (Qobuz, Spotify, etc.) are
// unlikely to be present in MPD's music database.
let albums = match db::albums_without_cover_from_mpd(conn) {
Ok(a) => a,
Err(e) => {
eprintln!("[error] Failed to query albums without cover: {}", e);
@@ -971,10 +972,10 @@ pub fn run_mpd_cover_enrich_targeted(
conn: &Connection,
needed: &std::collections::HashSet<(String, String)>,
) {
// Start from albums that genuinely have no cover yet, then narrow to the
// set the caller cares about. This avoids redundant MPD round-trips for
// albums that already have art.
let albums = match db::albums_without_cover(conn) {
// Start from albums that have no cover AND were scrobbled via MPD — albums
// from MPRIS-only players are excluded because MPD won't have those files.
// Then narrow further to the set the caller cares about.
let albums = match db::albums_without_cover_from_mpd(conn) {
Ok(a) => a,
Err(e) => {
eprintln!("[error] Failed to query albums without cover: {}", e);