fix: AcoustID decides any one-album mismatch the lengths cannot, not only copies each cut to its slot (#6169)
release / govulncheck (push) Successful in 13s
release / web (push) Successful in 1m21s
release / go (push) Successful in 1m37s
release / integration (push) Successful in 5m3s
release / android (push) Successful in 5m6s
release / Build signed APK (releases and dev) (push) Successful in 5m14s
release / Attach APK to the Release (tag releases only) (push) Skipped
release / Build + push container image (push) Successful in 15s
release / Verify release artifacts (tag releases only) (push) Skipped

The first pass on the operator's library held 16 groups. In several, every
copy's own lookup names one recording (Wombats Record Shop/Tormentor,
Alchemist (2)/Prelude, Monday Chill 8/9, 404sessions), but one copy sits 3-10s
from its slot, so the every-copy-fits precondition kept AcoustID out. Now:
copies whose lookups all agree are that recording, whatever their
fingerprints read; copies of the same audio are asked about as before; and
the track list places the recording in one copy's slot, or none. Copies
filed as one song are not settled here.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-20 10:52:42 -04:00
co-authored by Claude Opus 5.5
parent 18d31e9cdd
commit 3a482bd715
3 changed files with 103 additions and 64 deletions
@@ -499,6 +499,56 @@ func TestResolveDuplicates_KeepsTheCopyAcoustIDNames_Integration(t *testing.T) {
}
}
// Copies whose own lookups all name Record Shop's recording are that
// recording, though their fingerprints differ a little and one is six seconds
// from Tormentor's length, too near for the lengths to decide (the operator's
// Wombats and Monday Chill groups, 2026-10-20). With no lookups, copies that
// far apart are not asked about.
func TestResolveDuplicates_AgreeingLookupsDecideAnAcousticGroup_Integration(t *testing.T) {
setup := func(t *testing.T) oneAlbumFixture {
f := seedTrimmedAlbum(t)
for _, stmt := range []string{
`UPDATE duplicate_groups SET tier = 'acoustic', worst_bit_error_rate = 0.04`,
`UPDATE mb_release_tracks SET length_ms = 226000 WHERE title = 'Tormentor'`,
} {
if _, err := f.pool.Exec(context.Background(), stmt); err != nil {
t.Fatalf("exec %q: %v", stmt, err)
}
}
return f
}
t.Run("agreeing", func(t *testing.T) {
f := setup(t)
if _, err := f.pool.Exec(context.Background(),
`INSERT INTO track_acoustid_lookups (track_id, state, candidates, recording_mbid)
VALUES ($1, 'matched', 1, 'rec-record-shop'), ($2, 'matched', 1, 'rec-record-shop')`,
f.a.ID, f.b.ID); err != nil {
t.Fatal(err)
}
res, err := ResolveDuplicates(context.Background(), f.pool, nil, "", true)
if err != nil {
t.Fatal(err)
}
if res.WrongFiles != 1 || exists(f.aPath) || !exists(f.bPath) {
t.Fatalf("result %+v, tormentor exists %v, record shop exists %v; want only Tormentor's copy removed",
res, exists(f.aPath), exists(f.bPath))
}
})
t.Run("unknown", func(t *testing.T) {
f := setup(t)
asked := 0
res, err := ResolveDuplicatesWith(context.Background(), f.pool, nil, "", true, ResolveSources{
Identify: func(context.Context, string) ([]string, error) { asked++; return nil, nil },
})
if err != nil {
t.Fatal(err)
}
if asked != 0 || res.WrongFiles != 0 || !exists(f.aPath) || !exists(f.bPath) {
t.Fatalf("asked %d, result %+v; want nothing asked or removed for copies that may be two takes", asked, res)
}
})
}
// AcoustID knows the recording as no song of the album: every copy goes. With
// AcoustID unreachable, nothing is decided and the group waits.
func TestResolveDuplicates_TrimmedCopiesAcoustIDCannotName_Integration(t *testing.T) {