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
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:
@@ -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)
|
||||
|
||||
@@ -560,3 +560,23 @@ func (q *Queries) RejectLidarrRequest(ctx context.Context, arg RejectLidarrReque
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const setLidarrRequestAlbumMbid = `-- name: SetLidarrRequestAlbumMbid :exec
|
||||
UPDATE lidarr_requests
|
||||
SET lidarr_album_mbid = $2,
|
||||
updated_at = now()
|
||||
WHERE id = $1
|
||||
`
|
||||
|
||||
type SetLidarrRequestAlbumMbidParams struct {
|
||||
ID pgtype.UUID
|
||||
LidarrAlbumMbid *string
|
||||
}
|
||||
|
||||
// #5241: repoint a request at the album's release group. Requests made before
|
||||
// the release-group read named albums by MusicBrainz release id, which Lidarr
|
||||
// does not index; the reconciler rewrites them once it has resolved the group.
|
||||
func (q *Queries) SetLidarrRequestAlbumMbid(ctx context.Context, arg SetLidarrRequestAlbumMbidParams) error {
|
||||
_, err := q.db.Exec(ctx, setLidarrRequestAlbumMbid, arg.ID, arg.LidarrAlbumMbid)
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -114,6 +114,7 @@ const listAlbumsDueReacquisition = `-- name: ListAlbumsDueReacquisition :many
|
||||
SELECT albums.id AS album_id,
|
||||
albums.title AS album_title,
|
||||
albums.mbid AS album_mbid,
|
||||
albums.release_group_mbid AS album_release_group_mbid,
|
||||
artists.id AS artist_id,
|
||||
artists.name AS artist_name,
|
||||
artists.mbid AS artist_mbid,
|
||||
@@ -135,7 +136,7 @@ SELECT albums.id AS album_id,
|
||||
* POWER(2, GREATEST(COALESCE(r.attempts, 0) - 1, 0)))::int,
|
||||
$3::int))
|
||||
)
|
||||
GROUP BY albums.id, albums.title, albums.mbid,
|
||||
GROUP BY albums.id, albums.title, albums.mbid, albums.release_group_mbid,
|
||||
artists.id, artists.name, artists.mbid, r.attempts, r.last_attempt_at
|
||||
ORDER BY r.last_attempt_at NULLS FIRST, albums.sort_title
|
||||
LIMIT $4
|
||||
@@ -149,14 +150,15 @@ type ListAlbumsDueReacquisitionParams struct {
|
||||
}
|
||||
|
||||
type ListAlbumsDueReacquisitionRow struct {
|
||||
AlbumID pgtype.UUID
|
||||
AlbumTitle string
|
||||
AlbumMbid *string
|
||||
ArtistID pgtype.UUID
|
||||
ArtistName string
|
||||
ArtistMbid *string
|
||||
MissingTrackCount int64
|
||||
Attempts int32
|
||||
AlbumID pgtype.UUID
|
||||
AlbumTitle string
|
||||
AlbumMbid *string
|
||||
AlbumReleaseGroupMbid *string
|
||||
ArtistID pgtype.UUID
|
||||
ArtistName string
|
||||
ArtistMbid *string
|
||||
MissingTrackCount int64
|
||||
Attempts int32
|
||||
}
|
||||
|
||||
// The sweeper's selection. An album qualifies when:
|
||||
@@ -194,6 +196,7 @@ func (q *Queries) ListAlbumsDueReacquisition(ctx context.Context, arg ListAlbums
|
||||
&i.AlbumID,
|
||||
&i.AlbumTitle,
|
||||
&i.AlbumMbid,
|
||||
&i.AlbumReleaseGroupMbid,
|
||||
&i.ArtistID,
|
||||
&i.ArtistName,
|
||||
&i.ArtistMbid,
|
||||
|
||||
@@ -152,6 +152,22 @@ UPDATE albums
|
||||
updated_at = now()
|
||||
WHERE id = $1 AND release_group_mbid IS NULL;
|
||||
|
||||
-- name: GetReleaseGroupForReleaseMbid :one
|
||||
-- #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.
|
||||
SELECT release_group_mbid::text
|
||||
FROM albums
|
||||
WHERE mbid = $1 AND release_group_mbid IS NOT NULL
|
||||
LIMIT 1;
|
||||
|
||||
-- name: SetReleaseGroupForReleaseMbidIfNull :exec
|
||||
-- #5241: cache a MusicBrainz-resolved release group onto the album row that
|
||||
-- holds the release, filling only a NULL.
|
||||
UPDATE albums
|
||||
SET release_group_mbid = sqlc.arg(release_group_mbid)::text,
|
||||
updated_at = now()
|
||||
WHERE mbid = sqlc.arg(release_mbid)::text AND release_group_mbid IS NULL;
|
||||
|
||||
-- name: ListAlbumsMissingMbidWithTrack :many
|
||||
-- One-shot MBID backfill: returns each album where mbid IS NULL alongside
|
||||
-- one of its tracks' file_path so the worker can re-read tags. LIMIT
|
||||
|
||||
@@ -119,3 +119,12 @@ UPDATE lidarr_requests
|
||||
WHERE id = $1
|
||||
AND status = 'approved'
|
||||
AND lidarr_add_confirmed_at IS NULL;
|
||||
|
||||
-- name: SetLidarrRequestAlbumMbid :exec
|
||||
-- #5241: repoint a request at the album's release group. Requests made before
|
||||
-- the release-group read named albums by MusicBrainz release id, which Lidarr
|
||||
-- does not index; the reconciler rewrites them once it has resolved the group.
|
||||
UPDATE lidarr_requests
|
||||
SET lidarr_album_mbid = $2,
|
||||
updated_at = now()
|
||||
WHERE id = $1;
|
||||
|
||||
@@ -40,6 +40,7 @@ RETURNING *;
|
||||
SELECT albums.id AS album_id,
|
||||
albums.title AS album_title,
|
||||
albums.mbid AS album_mbid,
|
||||
albums.release_group_mbid AS album_release_group_mbid,
|
||||
artists.id AS artist_id,
|
||||
artists.name AS artist_name,
|
||||
artists.mbid AS artist_mbid,
|
||||
@@ -61,7 +62,7 @@ SELECT albums.id AS album_id,
|
||||
* POWER(2, GREATEST(COALESCE(r.attempts, 0) - 1, 0)))::int,
|
||||
sqlc.arg(backoff_max_hours)::int))
|
||||
)
|
||||
GROUP BY albums.id, albums.title, albums.mbid,
|
||||
GROUP BY albums.id, albums.title, albums.mbid, albums.release_group_mbid,
|
||||
artists.id, artists.name, artists.mbid, r.attempts, r.last_attempt_at
|
||||
ORDER BY r.last_attempt_at NULLS FIRST, albums.sort_title
|
||||
LIMIT sqlc.arg(page_limit);
|
||||
|
||||
Reference in New Issue
Block a user