fix(artwork): precache the cover variant the UI actually requests

precache built its resizedItem without setting square, so it warmed
h-<hash>.<size>.false.<quality>. The list surfaces - album grid, artwork avatars,
playlist and radio details - all request square covers, so the warmed entry was
never read and every grid cover stayed a cold miss on first view.

Set square on the precache item so the key matches the request path. The existing
specs asserted the '.300.false.' key and were updated accordingly.
This commit is contained in:
Deluan 2026-07-26 01:07:40 -04:00
parent de2b2e4b78
commit 0ce5bd4148
2 changed files with 5 additions and 2 deletions

View File

@ -319,9 +319,11 @@ func (w *Worker) precache(ctx context.Context, got *acquired) {
return
}
// Same key as the serving path (hash/size/square); only the source of the bytes differs.
// square matches what the list surfaces request, otherwise this warms a key nothing reads.
item := &resizedItem{
hash: got.ia.Hash,
size: conf.Server.UICoverArtSize,
square: true,
lastUpdate: got.ia.UpdatedAt,
ffmpeg: w.deps.ffmpeg,
open: func() (io.ReadCloser, error) { return io.NopCloser(bytes.NewReader(got.data)), nil },

View File

@ -562,7 +562,8 @@ var _ = Describe("Worker", func() {
Expect(err).ToNot(HaveOccurred())
Expect(n).To(Equal(1))
Expect(imgCache.getKeys()).To(ContainElement(ContainSubstring(".300.false.")))
// The list surfaces request square covers, so warming any other key is wasted work.
Expect(imgCache.getKeys()).To(ContainElement(ContainSubstring(".300.true.")))
})
It("skips warming when precache is disabled", func() {
@ -593,7 +594,7 @@ var _ = Describe("Worker", func() {
// from the bytes handed in. Probing with a source that refuses to open proves it
// is really cached rather than re-read on demand.
probe := &resizedItem{
hash: ia.Hash, size: 300, lastUpdate: ia.UpdatedAt, ffmpeg: ffm,
hash: ia.Hash, size: 300, square: true, lastUpdate: ia.UpdatedAt, ffmpeg: ffm,
open: func() (io.ReadCloser, error) { return nil, errors.New("precache must not re-read the source") },
}
stream, err := imgCache.Get(ctx, probe)