feat(library): store each album's MusicBrainz release-group id (M483 #5242)
release / govulncheck (push) Successful in 22s
release / web (push) Successful in 1m14s
release / go (push) Successful in 1m33s
release / integration (push) Successful in 4m36s
release / Attach APK to the Release (tag releases only) (push) Canceled after 0s
release / Build + push container image (push) Canceled after 0s
release / Verify release artifacts (tag releases only) (push) Canceled after 0s
release / android (push) Canceled after 5m24s
release / Build signed APK (releases and dev) (push) Canceled after 5m29s
release / govulncheck (push) Successful in 22s
release / web (push) Successful in 1m14s
release / go (push) Successful in 1m33s
release / integration (push) Successful in 4m36s
release / Attach APK to the Release (tag releases only) (push) Canceled after 0s
release / Build + push container image (push) Canceled after 0s
release / Verify release artifacts (tag releases only) (push) Canceled after 0s
release / android (push) Canceled after 5m24s
release / Build signed APK (releases and dev) (push) Canceled after 5m29s
albums.mbid is the release id (Picard's musicbrainz_albumid, one edition). Lidarr names albums by release group, so re-acquisition and request completion need that id too (#5241). Migration 0070 adds albums.release_group_mbid (nullable, non-unique index: several releases share a group). The scanner reads musicbrainz_releasegroupid through extractReleaseGroupMBID, writes it on insert and heals it onto existing rows when NULL. tagReadVersion goes to 3 so the next scan fills it for the library already indexed, bound by tag reads (no ffprobe, no decode). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -308,3 +308,80 @@ func TestScanner_AdoptsMovedFile_Integration(t *testing.T) {
|
||||
t.Errorf("tracks = %d, want 8 — a rename must not add a row", total)
|
||||
}
|
||||
}
|
||||
|
||||
// TestScanner_ReleaseGroupMBID_Integration is #5241's scan half: a new album
|
||||
// takes its release-group id from the tag, and an album indexed before this
|
||||
// read existed gets it on the next scan, through the tagReadVersion bump,
|
||||
// without its file changing.
|
||||
func TestScanner_ReleaseGroupMBID_Integration(t *testing.T) {
|
||||
if testing.Short() {
|
||||
t.Skip("skipping scanner integration in -short mode")
|
||||
}
|
||||
dsn := os.Getenv("MINSTREL_TEST_DATABASE_URL")
|
||||
if dsn == "" {
|
||||
t.Skip("MINSTREL_TEST_DATABASE_URL not set")
|
||||
}
|
||||
ctx := context.Background()
|
||||
logger := slog.New(slog.NewTextHandler(io.Discard, nil))
|
||||
|
||||
if err := db.Migrate(dsn, logger); err != nil {
|
||||
t.Fatalf("migrate: %v", err)
|
||||
}
|
||||
pool, err := pgxpool.New(ctx, dsn)
|
||||
if err != nil {
|
||||
t.Fatalf("pool: %v", err)
|
||||
}
|
||||
t.Cleanup(pool.Close)
|
||||
if _, err := pool.Exec(ctx, "TRUNCATE tracks, albums, artists RESTART IDENTITY CASCADE"); err != nil {
|
||||
t.Fatalf("truncate: %v", err)
|
||||
}
|
||||
|
||||
const (
|
||||
groupA = "aaaaaaaa-1111-2222-3333-444444444444"
|
||||
groupB = "bbbbbbbb-1111-2222-3333-444444444444"
|
||||
)
|
||||
root := t.TempDir()
|
||||
writeTestMP3(t, filepath.Join(root, "rg/A/01.mp3"), map[string]string{
|
||||
"TIT2": "One", "TPE1": "Artist RG", "TALB": "Album A",
|
||||
"TXXX": "MusicBrainz Release Group Id\x00" + groupA,
|
||||
})
|
||||
pathB := filepath.Join(root, "rg/B/01.mp3")
|
||||
writeTestMP3(t, pathB, map[string]string{
|
||||
"TIT2": "Two", "TPE1": "Artist RG", "TALB": "Album B",
|
||||
"TXXX": "MusicBrainz Release Group Id\x00" + groupB,
|
||||
})
|
||||
|
||||
scanner := New(pool, logger, []string{root}, nil)
|
||||
if _, err := scanner.Scan(ctx, nil); err != nil {
|
||||
t.Fatalf("first scan: %v", err)
|
||||
}
|
||||
groupOf := func(title string) *string {
|
||||
t.Helper()
|
||||
var rg *string
|
||||
if err := pool.QueryRow(ctx, "SELECT release_group_mbid FROM albums WHERE title = $1", title).Scan(&rg); err != nil {
|
||||
t.Fatalf("album %q: %v", title, err)
|
||||
}
|
||||
return rg
|
||||
}
|
||||
if rg := groupOf("Album A"); rg == nil || *rg != groupA {
|
||||
t.Fatalf("new album release group = %v, want %s", rg, groupA)
|
||||
}
|
||||
|
||||
// Album B as a library indexed under tag-read version 2 left it: no
|
||||
// release group, file untouched since.
|
||||
if _, err := pool.Exec(ctx, "UPDATE albums SET release_group_mbid = NULL WHERE title = 'Album B'"); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if _, err := pool.Exec(ctx, "UPDATE tracks SET tag_read_version = 2 WHERE file_path = $1", pathB); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if _, err := scanner.Scan(ctx, nil); err != nil {
|
||||
t.Fatalf("second scan: %v", err)
|
||||
}
|
||||
if rg := groupOf("Album B"); rg == nil || *rg != groupB {
|
||||
t.Errorf("existing album release group after rescan = %v, want %s", rg, groupB)
|
||||
}
|
||||
if rg := groupOf("Album A"); rg == nil || *rg != groupA {
|
||||
t.Errorf("album A release group changed to %v", rg)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user