mirror of
https://github.com/navidrome/navidrome.git
synced 2026-04-28 03:19:38 +00:00
fix(artwork): return imagesUpdatedAt in LastUpdated when cover art changes
When cover art (cover.jpg) is updated in an album folder, the HTTP Last-Modified header was incorrectly returning album.UpdatedAt (which only tracks media file changes) instead of imagesUpdatedAt (which tracks cover art changes). This caused browsers to use their cached cover art because the Last-Modified header didn't change, even though the actual cover art image data was new (due to cache key changing based on imagesUpdatedAt). The fix ensures LastUpdated() returns a.lastUpdate (which is the max of album.UpdatedAt and imagesUpdatedAt) instead of always returning album.UpdatedAt. Fixes navidrome/navidrome#5377
This commit is contained in:
parent
155e293f4d
commit
9a741859f6
2 changed files with 39 additions and 2 deletions
|
|
@ -7,9 +7,9 @@ import (
|
|||
"image/jpeg"
|
||||
"image/png"
|
||||
"io"
|
||||
|
||||
"os"
|
||||
"path/filepath"
|
||||
"time"
|
||||
|
||||
_ "github.com/gen2brain/webp"
|
||||
|
||||
|
|
@ -146,6 +146,43 @@ var _ = Describe("Artwork", func() {
|
|||
Entry(nil, " embedded , front.* , cover.*,folder.*", "tests/fixtures/artist/an-album/test.mp3"),
|
||||
)
|
||||
})
|
||||
Context("LastUpdated returns the correct timestamp", func() {
|
||||
It("returns album UpdatedAt when imagesUpdatedAt is older", func() {
|
||||
// Set up album with recent UpdatedAt but folder with older ImagesUpdatedAt
|
||||
now := time.Now().Truncate(time.Second)
|
||||
albumOld := model.Album{ID: "old-album", Name: "Old Album", UpdatedAt: now, FolderIDs: []string{"folder1"}}
|
||||
folderRepo.result = []model.Folder{{
|
||||
Path: "tests/fixtures/artist/an-album",
|
||||
ImagesUpdatedAt: now.Add(-1 * time.Hour), // older than album.UpdatedAt
|
||||
ImageFiles: []string{"cover.jpg"},
|
||||
}}
|
||||
ds.Album(ctx).(*tests.MockAlbumRepo).SetData(model.Albums{albumOld})
|
||||
ds.MediaFile(ctx).(*tests.MockMediaFileRepo).SetData(model.MediaFiles{})
|
||||
|
||||
ar, err := newAlbumArtworkReader(ctx, aw, albumOld.CoverArtID(), nil)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(ar.LastUpdated()).To(Equal(now)) // should return album.UpdatedAt (now)
|
||||
})
|
||||
It("returns imagesUpdatedAt when it is newer than album UpdatedAt", func() {
|
||||
// Set up album with old UpdatedAt but folder with recent ImagesUpdatedAt
|
||||
// This simulates the case where cover art was updated but no media files changed
|
||||
now := time.Now().Truncate(time.Second)
|
||||
albumOld := model.Album{ID: "old-album2", Name: "Old Album 2", UpdatedAt: now.Add(-24 * time.Hour), FolderIDs: []string{"folder1"}}
|
||||
newerImagesUpdatedAt := now.Add(-1 * time.Hour) // cover art was updated 1 hour ago
|
||||
folderRepo.result = []model.Folder{{
|
||||
Path: "tests/fixtures/artist/an-album",
|
||||
ImagesUpdatedAt: newerImagesUpdatedAt,
|
||||
ImageFiles: []string{"cover.jpg"},
|
||||
}}
|
||||
ds.Album(ctx).(*tests.MockAlbumRepo).SetData(model.Albums{albumOld})
|
||||
ds.MediaFile(ctx).(*tests.MockMediaFileRepo).SetData(model.MediaFiles{})
|
||||
|
||||
ar, err := newAlbumArtworkReader(ctx, aw, albumOld.CoverArtID(), nil)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
// Should return imagesUpdatedAt (newer), not album.UpdatedAt (older)
|
||||
Expect(ar.LastUpdated()).To(Equal(newerImagesUpdatedAt))
|
||||
})
|
||||
})
|
||||
})
|
||||
Describe("artistArtworkReader", func() {
|
||||
Context("Multiple covers", func() {
|
||||
|
|
|
|||
|
|
@ -72,7 +72,7 @@ func (a *albumArtworkReader) Key() string {
|
|||
)
|
||||
}
|
||||
func (a *albumArtworkReader) LastUpdated() time.Time {
|
||||
return a.album.UpdatedAt
|
||||
return a.lastUpdate
|
||||
}
|
||||
|
||||
func (a *albumArtworkReader) Reader(ctx context.Context) (io.ReadCloser, string, error) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue