mirror of
https://github.com/navidrome/navidrome.git
synced 2026-10-18 07:30:29 +00:00
fix(artwork): partition the absent states instead of nesting them
ABSENT with FAILED beside it read as two buckets when the second was inside the first, and "OF WHICH FAILED" fixed the ambiguity by admitting it rather than removing it. The two columns are now disjoint and sum to the absent total: NO IMAGE was answered, FAILED gave up. The struct holds the same split the table prints, so the subtraction happens once where the counts are collected. The collectStatus fixture had two absent artists and no failure among them, which made noImage and the absent total identical and left the subtraction unverified — dropping it broke nothing. One of the two now carries a last_failure.
This commit is contained in:
parent
4535465cff
commit
e92a90f5a9
@ -147,11 +147,11 @@ type sourceCount struct {
|
||||
count int64
|
||||
}
|
||||
|
||||
// absentCount partitions a kind's absent states: noImage was answered, failed gave up.
|
||||
type absentCount struct {
|
||||
kind model.Kind
|
||||
count int64
|
||||
// afterFailure is the subset that gave up rather than being told "no image".
|
||||
afterFailure int64
|
||||
kind model.Kind
|
||||
noImage int64
|
||||
failed int64
|
||||
}
|
||||
|
||||
type statusReport struct {
|
||||
@ -199,7 +199,7 @@ func collectStatus(ctx context.Context, ds model.DataStore) (statusReport, error
|
||||
if err != nil {
|
||||
return rep, fmt.Errorf("counting failed %s artwork: %w", k, err)
|
||||
}
|
||||
rep.absent = append(rep.absent, absentCount{kind: k, count: n, afterFailure: failed})
|
||||
rep.absent = append(rep.absent, absentCount{kind: k, noImage: n - failed, failed: failed})
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -229,12 +229,12 @@ func formatStatus(rep statusReport) string {
|
||||
}
|
||||
|
||||
fmt.Fprintln(w, "\nAbsent (resolved, no image found)")
|
||||
fmt.Fprintln(w, " KIND\tABSENT\tOF WHICH FAILED")
|
||||
fmt.Fprintln(w, " KIND\tNO IMAGE\tFAILED")
|
||||
for _, a := range rep.absent {
|
||||
fmt.Fprintf(w, " %s\t%d\t%d\n", a.kind, a.count, a.afterFailure)
|
||||
fmt.Fprintf(w, " %s\t%d\t%d\n", a.kind, a.noImage, a.failed)
|
||||
}
|
||||
fmt.Fprintln(w, " (nothing retries these; 'artwork reprocess --source absent' retries all of them)")
|
||||
fmt.Fprintln(w, " (failed = gave up rather than being answered, so the subset most likely to resolve;\n"+
|
||||
fmt.Fprintln(w, " (nothing retries these; 'artwork reprocess --source absent' retries both columns)")
|
||||
fmt.Fprintln(w, " (failed = gave up rather than being answered, so the ones most likely to resolve;\n"+
|
||||
" 'artwork reprocess --source failed' retries just those)")
|
||||
|
||||
fmt.Fprintln(w, "\nConfig")
|
||||
|
||||
@ -816,7 +816,9 @@ var _ = Describe("collectStatus", func() {
|
||||
}
|
||||
put(model.KindArtistArtwork, "ar-1", "external:deezer", "h1", time.Now())
|
||||
put(model.KindArtistArtwork, "ar-2", "", "", time.Now().Add(-24*time.Hour))
|
||||
put(model.KindArtistArtwork, "ar-3", "", "", time.Now())
|
||||
// ar-3 is absent because it gave up, so the two absent artists split across the columns.
|
||||
Expect(art.PutItemArtwork(&model.ItemArtwork{ItemKind: "ar", ItemID: "ar-3",
|
||||
ImageType: model.ImageTypePrimary, LastFailure: "[]", AttemptedAt: time.Now()})).To(Succeed())
|
||||
put(model.KindAlbumArtwork, "al-1", "folder", "h2", time.Now())
|
||||
Expect(queue.Enqueue(model.ArtworkQueueItem{ItemKind: "ar", ItemID: "ar-9",
|
||||
ImageType: model.ImageTypePrimary, Priority: model.ArtworkPriorityBackfill})).To(Succeed())
|
||||
@ -833,7 +835,8 @@ var _ = Describe("collectStatus", func() {
|
||||
sourceCount{kind: model.KindArtistArtwork, source: "", count: 2},
|
||||
sourceCount{kind: model.KindAlbumArtwork, source: "folder", count: 1},
|
||||
))
|
||||
Expect(rep.absent).To(ContainElement(absentCount{kind: model.KindArtistArtwork, count: 2}))
|
||||
Expect(rep.absent).To(ContainElement(absentCount{kind: model.KindArtistArtwork, noImage: 1, failed: 1}),
|
||||
"two absent artists, one answered and one that gave up")
|
||||
})
|
||||
|
||||
It("compares the stored fingerprint against the current one", func() {
|
||||
@ -867,7 +870,7 @@ var _ = Describe("formatStatus", func() {
|
||||
{kind: model.KindArtistArtwork, source: "", count: 2},
|
||||
},
|
||||
absent: []absentCount{
|
||||
{kind: model.KindArtistArtwork, count: 2, afterFailure: 1},
|
||||
{kind: model.KindArtistArtwork, noImage: 1, failed: 1},
|
||||
},
|
||||
inputs: []artwork.FingerprintInput{{Name: "Agents", Value: "deezer,lastfm"}},
|
||||
stored: "abc123",
|
||||
@ -900,10 +903,10 @@ var _ = Describe("formatStatus", func() {
|
||||
Expect(sources).To(MatchRegexp(`artist\s+absent\s+2`))
|
||||
})
|
||||
|
||||
It("presents the failed count as a subset of the absent total, not a second bucket", func() {
|
||||
It("partitions the absent states into answered and gave up", func() {
|
||||
out := block(formatStatus(rep), "Absent (resolved, no image found)")
|
||||
Expect(out).To(ContainSubstring("OF WHICH FAILED"))
|
||||
Expect(out).To(MatchRegexp(`artist\s+2\s+1`), "2 absent, of which 1 failed")
|
||||
Expect(out).To(ContainSubstring("NO IMAGE"))
|
||||
Expect(out).To(MatchRegexp(`artist\s+1\s+1`), "1 answered plus 1 failed, summing to 2 absent")
|
||||
Expect(formatStatus(rep)).To(ContainSubstring("artwork reprocess --source failed"))
|
||||
})
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user