feat(lidarr): ask Lidarr for release groups; repair stored release-id requests (M483 #5244)
release / go (push) Successful in 2m33s
release / web (push) Successful in 1m41s
release / govulncheck (push) Successful in 22s
release / integration (push) Successful in 6m0s
release / android (push) Successful in 6m7s
release / Build signed APK (releases and dev) (push) Successful in 6m8s
release / Attach APK to the Release (tag releases only) (push) Skipped
release / Build + push container image (push) Successful in 1m43s
release / Verify release artifacts (tag releases only) (push) Skipped

Lidarr's metadata is keyed by MusicBrainz release group, but re-acquisition
requested albums by their release id, so every add came back "not found".

- Sweeper requests an album by its tag-supplied release group, else the one
  MusicBrainz names (cached onto the album). An album MusicBrainz cannot name
  is skipped and counted, with no attempt spent.
- Reconciler: an add refused as not found re-reads the request's album id as
  a release (library first, then MusicBrainz), rewrites the request to the
  group and adds again. This repairs the requests already stored.
- Completion matches an album by release id or release group, and only once a
  track of it is on disk, so a re-acquisition request no longer completes
  against the row of the album it is trying to bring back.

Closes #5241.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-07 11:38:45 -04:00
co-authored by Claude Opus 5.5
parent 2b4e274b12
commit e509d7d5a9
11 changed files with 596 additions and 27 deletions
+35
View File
@@ -248,6 +248,22 @@ func (q *Queries) GetAlbumsByIDs(ctx context.Context, dollar_1 []pgtype.UUID) ([
return items, nil
}
const getReleaseGroupForReleaseMbid = `-- name: GetReleaseGroupForReleaseMbid :one
SELECT release_group_mbid::text
FROM albums
WHERE mbid = $1 AND release_group_mbid IS NOT NULL
LIMIT 1
`
// #5241: the release group the library already knows for a release id, so a
// request carrying a release id can be repaired without asking MusicBrainz.
func (q *Queries) GetReleaseGroupForReleaseMbid(ctx context.Context, mbid *string) (string, error) {
row := q.db.QueryRow(ctx, getReleaseGroupForReleaseMbid, mbid)
var release_group_mbid string
err := row.Scan(&release_group_mbid)
return release_group_mbid, err
}
const listAlbumsAlphaByArtist = `-- name: ListAlbumsAlphaByArtist :many
SELECT albums.id, albums.title, albums.sort_title, albums.artist_id, albums.release_date, albums.mbid, albums.cover_art_path, albums.created_at, albums.updated_at, albums.cover_art_source, albums.cover_art_sources_version, albums.release_group_mbid, artists.sort_name AS artist_sort_name
FROM albums
@@ -852,6 +868,25 @@ func (q *Queries) SetAlbumReleaseGroupMbidIfNull(ctx context.Context, arg SetAlb
return err
}
const setReleaseGroupForReleaseMbidIfNull = `-- name: SetReleaseGroupForReleaseMbidIfNull :exec
UPDATE albums
SET release_group_mbid = $1::text,
updated_at = now()
WHERE mbid = $2::text AND release_group_mbid IS NULL
`
type SetReleaseGroupForReleaseMbidIfNullParams struct {
ReleaseGroupMbid string
ReleaseMbid string
}
// #5241: cache a MusicBrainz-resolved release group onto the album row that
// holds the release, filling only a NULL.
func (q *Queries) SetReleaseGroupForReleaseMbidIfNull(ctx context.Context, arg SetReleaseGroupForReleaseMbidIfNullParams) error {
_, err := q.db.Exec(ctx, setReleaseGroupForReleaseMbidIfNull, arg.ReleaseGroupMbid, arg.ReleaseMbid)
return err
}
const upsertAlbum = `-- name: UpsertAlbum :one
INSERT INTO albums (title, sort_title, artist_id, release_date, mbid, cover_art_path, release_group_mbid)
VALUES ($1, $2, $3, $4, $5, $6, $7)