From f016192eec1484860d1a6bea8ab2baee41a0e30d Mon Sep 17 00:00:00 2001 From: Deluan Date: Thu, 23 Jul 2026 05:30:47 -0400 Subject: [PATCH] fix(artwork): requeue playlist cover when its track set changes A generated-grid cover went stale after track mutations: nothing re-resolved the playlist's artwork, and the request path deliberately never rebuilds the grid, so serveEntity kept returning the old grid hash indefinitely. Enqueue pl artwork from refreshCounters (the choke point for every track-set change); no clear, so the old cover keeps serving until the worker rebuilds. --- persistence/playlist_repository.go | 7 +++++++ persistence/playlist_repository_test.go | 15 +++++++++++++++ 2 files changed, 22 insertions(+) diff --git a/persistence/playlist_repository.go b/persistence/playlist_repository.go index e984b8852..397838f07 100644 --- a/persistence/playlist_repository.go +++ b/persistence/playlist_repository.go @@ -324,6 +324,13 @@ func (r *playlistRepository) refreshCounters(pls *model.Playlist) error { pls.SongCount = int(res.Count) pls.Duration = res.Duration pls.Size = int64(res.Size) + // The generated 2x2 grid depends on the track set, so re-resolve the cover whenever it + // changes. No clear: the old cover keeps serving until the worker rebuilds (no flicker). + item := model.ArtworkQueueItem{ItemKind: "pl", ItemID: pls.ID, ImageType: model.ImageTypePrimary, + Priority: model.ArtworkPriorityScan} + if err := NewArtworkQueueRepository(r.ctx, r.db).Enqueue(item); err != nil { + log.Warn(r.ctx, "could not enqueue playlist artwork after content change", "id", pls.ID, err) + } return nil } diff --git a/persistence/playlist_repository_test.go b/persistence/playlist_repository_test.go index 8dc86d887..ec5259400 100644 --- a/persistence/playlist_repository_test.go +++ b/persistence/playlist_repository_test.go @@ -260,6 +260,21 @@ var _ = Describe("PlaylistRepository", func() { Expect(repo.Exists(newPls.ID)).To(BeFalse()) }) + It("enqueues the playlist's artwork when its track set changes", func() { + ctx := request.WithUser(log.NewContext(GinkgoT().Context()), model.User{ID: "userid", UserName: "userid", IsAdmin: true}) + newPls := model.Playlist{Name: "Grid PL", OwnerID: "userid"} + newPls.AddMediaFilesByID([]string{"1001", "1002"}) + Expect(repo.Put(&newPls)).To(Succeed()) + DeferCleanup(func() { _ = repo.Delete(newPls.ID) }) + + queued, err := NewArtworkQueueRepository(ctx, GetDBXBuilder()).DequeueBatch(1000) + Expect(err).ToNot(HaveOccurred()) + Expect(queued).To(ContainElement(SatisfyAll( + HaveField("ItemKind", "pl"), + HaveField("ItemID", newPls.ID), + ))) + }) + Describe("GetAll", func() { It("returns all playlists from DB", func() { all, err := repo.GetAll()