From e9c15d7fcb82ead74e9bcc4e8bfe09cf693cf16a Mon Sep 17 00:00:00 2001 From: Deluan Date: Thu, 23 Jul 2026 09:24:15 -0400 Subject: [PATCH] fix(artwork): don't stamp the album hash onto multi-disc tracks The hydration fallback assigned a found album hash to every fallback track, but a multi-disc track's CoverArtID emits a dc- id served from disc-specific art whose hash is unknown at hydration time. Advertising dc-..._ gave clients a content- version that never changes when the disc image does, breaking id-based refresh. Only stamp the album hash for single-disc tracks (DiscNumber == 0); multi-disc tracks stay unhashed and rely on the correct ETag returned by the served response. --- persistence/artwork_hydration_test.go | 11 +++++++++++ persistence/mediafile_repository.go | 9 +++++++-- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/persistence/artwork_hydration_test.go b/persistence/artwork_hydration_test.go index cb90591d9..d9c80e054 100644 --- a/persistence/artwork_hydration_test.go +++ b/persistence/artwork_hydration_test.go @@ -249,6 +249,17 @@ var _ = Describe("Artwork hydration", func() { Expect(byID["1003"].ImageAbsent).To(BeTrue()) }) + It("does not stamp a found album hash onto a multi-disc track (its dc- id is disc-served)", func() { + putInfo("al", "104", "alh104foundxxxxx") // songs 2002/2004 album is found + + byID := getByID() + + // 2002 is multi-disc (DiscNumber>0); CoverArtID emits a dc- id served from disc art of + // unknown identity, so it must not advertise the album's hash as its content-version. + Expect(byID["2002"].ImageHash).To(BeEmpty()) + Expect(byID["2002"].ImageAbsent).To(BeFalse()) + }) + It("keeps a multi-disc track requestable when its album is absent (disc art may resolve)", func() { putInfo("al", "104", "") // songs 2002/2004 album known-absent diff --git a/persistence/mediafile_repository.go b/persistence/mediafile_repository.go index 401e485e8..4cc93f4dd 100644 --- a/persistence/mediafile_repository.go +++ b/persistence/mediafile_repository.go @@ -247,9 +247,14 @@ func (r *mediaFileRepository) hydrateArtwork(mfs model.MediaFiles) { mf.ImageHash = ownInfo.Hash // own resolved art wins continue } - // Fallback (see MediaFile.CoverArtID): inherit a found album hash for optimistic caching. + // Fallback (see MediaFile.CoverArtID): inherit a found album hash for optimistic caching, + // but only for a single-disc track. A multi-disc track emits a dc- id served from + // disc-specific art of unknown identity, so stamping the album hash would advertise a + // wrong content-version; leave it bare (the served response still carries a correct ETag). if album, ok := albumInfos[mf.AlbumID]; ok && !album.Absent() { - mf.ImageHash = album.Hash + if mf.DiscNumber == 0 { + mf.ImageHash = album.Hash + } continue } // Nothing found. Mark absent only when serving would definitively yield a placeholder: