fix(lidarr): complete a request only when the album actually came back (#5263)
release / govulncheck (push) Failing after 33s
release / web (push) Successful in 1m21s
release / go (push) Successful in 1m44s
release / integration (push) Successful in 4m37s
release / android (push) Successful in 5m29s
release / Build signed APK (releases and dev) (push) Successful in 5m34s
release / Attach APK to the Release (tag releases only) (push) Skipped
release / Build + push container image (push) Skipped
release / Verify release artifacts (tag releases only) (push) Skipped
release / govulncheck (push) Failing after 33s
release / web (push) Successful in 1m21s
release / go (push) Successful in 1m44s
release / integration (push) Successful in 4m37s
release / android (push) Successful in 5m29s
release / Build signed APK (releases and dev) (push) Successful in 5m34s
release / Attach APK to the Release (tag releases only) (push) Skipped
release / Build + push container image (push) Skipped
release / Verify release artifacts (tag releases only) (push) Skipped
Re-acquisition targets albums with ANY track missing, and completion only asked for a track on disk, so the tracks that never left completed every re-acquisition request the moment Lidarr accepted the add (52 on the deploy, each ~150ms after its add). An album or track request now completes when an album named by its release or group has a track on disk AND either a track arrived after the request (a new album, or Lidarr fetching another release into its own row) or no track that was missing at the request is still missing. added_at is the arrival clock; updated_at moves on every tag re-read. Migration 0071 reopens completed album/track requests whose matched album fails that test, as approved with the match cleared; the Lidarr add stays confirmed, so nothing is re-sent. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -258,16 +258,32 @@ func (r *Reconciler) repointAtReleaseGroup(ctx context.Context, q *dbq.Queries,
|
||||
return row, true
|
||||
}
|
||||
|
||||
// albumForRequest finds the library album a request's album id names, by
|
||||
// release id or release group, and only once it has a track back on disk. A
|
||||
// re-acquisition request names an album whose row never went away; matching
|
||||
// the row alone would complete the request before Lidarr delivered anything.
|
||||
// albumForRequest finds the library album a request's album id ($1) names, by
|
||||
// release id or release group, once the request ($2 = requested_at) has been
|
||||
// answered: the album has a track on disk AND either
|
||||
//
|
||||
// - a track arrived after the request (a new album, or Lidarr fetching
|
||||
// another release of the group into its own row), or
|
||||
// - no track that was already missing when the request was made is still
|
||||
// missing (the lost files came back in place or were adopted at a new path).
|
||||
//
|
||||
// "Has a track on disk" alone is not enough (#5263): re-acquisition targets
|
||||
// albums with ANY track missing, so the tracks that never left satisfied it
|
||||
// the moment Lidarr accepted the add. added_at is the arrival clock because
|
||||
// nothing rewrites it; updated_at moves on every tag re-read.
|
||||
// An exact release match is preferred over another release of the group.
|
||||
const albumForRequest = `
|
||||
SELECT a.id
|
||||
FROM albums a
|
||||
WHERE (a.mbid = $1 OR a.release_group_mbid = $1)
|
||||
AND EXISTS (SELECT 1 FROM tracks t WHERE t.album_id = a.id AND t.missing_since IS NULL)
|
||||
AND (
|
||||
EXISTS (SELECT 1 FROM tracks t
|
||||
WHERE t.album_id = a.id AND t.missing_since IS NULL AND t.added_at > $2)
|
||||
OR NOT EXISTS (SELECT 1 FROM tracks t
|
||||
WHERE t.album_id = a.id AND t.missing_since IS NOT NULL
|
||||
AND t.missing_since < $2)
|
||||
)
|
||||
ORDER BY (a.mbid = $1) DESC, a.id
|
||||
LIMIT 1`
|
||||
|
||||
@@ -301,7 +317,7 @@ func (r *Reconciler) reconcileAlbum(ctx context.Context, q *dbq.Queries, row dbq
|
||||
return nil
|
||||
}
|
||||
var albumID pgtype.UUID
|
||||
err := r.pool.QueryRow(ctx, albumForRequest, *row.LidarrAlbumMbid).Scan(&albumID)
|
||||
err := r.pool.QueryRow(ctx, albumForRequest, *row.LidarrAlbumMbid, row.RequestedAt).Scan(&albumID)
|
||||
if err != nil {
|
||||
if isNoRows(err) {
|
||||
return nil
|
||||
@@ -327,7 +343,7 @@ func (r *Reconciler) reconcileTrack(ctx context.Context, q *dbq.Queries, row dbq
|
||||
}
|
||||
// Track-kind requests match via their parent album's MBID, not track.mbid.
|
||||
var albumID pgtype.UUID
|
||||
err := r.pool.QueryRow(ctx, albumForRequest, *row.LidarrAlbumMbid).Scan(&albumID)
|
||||
err := r.pool.QueryRow(ctx, albumForRequest, *row.LidarrAlbumMbid, row.RequestedAt).Scan(&albumID)
|
||||
if err != nil {
|
||||
if isNoRows(err) {
|
||||
return nil
|
||||
@@ -335,10 +351,10 @@ func (r *Reconciler) reconcileTrack(ctx context.Context, q *dbq.Queries, row dbq
|
||||
return err
|
||||
}
|
||||
|
||||
// Load any track from that album to set matched_track_id.
|
||||
// Load a track from that album to set matched_track_id, newest arrival first.
|
||||
var trackID pgtype.UUID
|
||||
err = r.pool.QueryRow(ctx,
|
||||
"SELECT id FROM tracks WHERE album_id = $1 AND missing_since IS NULL ORDER BY id LIMIT 1",
|
||||
"SELECT id FROM tracks WHERE album_id = $1 AND missing_since IS NULL ORDER BY added_at DESC, id LIMIT 1",
|
||||
albumID,
|
||||
).Scan(&trackID)
|
||||
if err != nil {
|
||||
|
||||
Reference in New Issue
Block a user