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>
131 lines
4.7 KiB
SQL
131 lines
4.7 KiB
SQL
-- name: CreateLidarrRequest :one
|
|
INSERT INTO lidarr_requests (
|
|
user_id, kind,
|
|
lidarr_artist_mbid, lidarr_album_mbid, lidarr_track_mbid,
|
|
artist_name, album_title, track_title
|
|
) VALUES ($1, $2, $3, $4, $5, $6, $7, $8)
|
|
RETURNING *;
|
|
|
|
-- name: GetLidarrRequestByID :one
|
|
SELECT * FROM lidarr_requests WHERE id = $1;
|
|
|
|
-- name: ListLidarrRequestsForUser :many
|
|
SELECT * FROM lidarr_requests
|
|
WHERE user_id = $1
|
|
ORDER BY requested_at DESC
|
|
LIMIT $2;
|
|
|
|
-- name: ListLidarrRequestsByStatus :many
|
|
SELECT * FROM lidarr_requests
|
|
WHERE status = $1
|
|
ORDER BY requested_at DESC
|
|
LIMIT $2;
|
|
|
|
-- name: ListApprovedLidarrRequestsForReconcile :many
|
|
SELECT * FROM lidarr_requests
|
|
WHERE status = 'approved'
|
|
ORDER BY decided_at ASC
|
|
LIMIT $1;
|
|
|
|
-- name: ApproveLidarrRequest :one
|
|
UPDATE lidarr_requests
|
|
SET status = 'approved',
|
|
quality_profile_id = $2,
|
|
root_folder_path = $3,
|
|
decided_at = now(),
|
|
decided_by = $4,
|
|
updated_at = now()
|
|
WHERE id = $1 AND status = 'pending'
|
|
RETURNING *;
|
|
|
|
-- name: RejectLidarrRequest :one
|
|
UPDATE lidarr_requests
|
|
SET status = 'rejected',
|
|
notes = $2,
|
|
decided_at = now(),
|
|
decided_by = $3,
|
|
updated_at = now()
|
|
WHERE id = $1 AND status = 'pending'
|
|
RETURNING *;
|
|
|
|
-- name: CancelLidarrRequest :one
|
|
-- $2 serves as both the ownership guard (user_id = $2) and the
|
|
-- decided_by audit field. The generated parameter struct names it
|
|
-- DecidedBy — callers must pass the cancelling user's UUID, and
|
|
-- a wrong UUID will silently no-op (zero rows updated) rather than
|
|
-- erroring at the SQL layer.
|
|
UPDATE lidarr_requests
|
|
SET status = 'rejected',
|
|
notes = 'cancelled by user',
|
|
decided_at = now(),
|
|
decided_by = $2,
|
|
updated_at = now()
|
|
WHERE id = $1 AND user_id = $2 AND status = 'pending'
|
|
RETURNING *;
|
|
|
|
-- name: CompleteLidarrRequest :one
|
|
-- Reconciler transitions an approved request to completed when its
|
|
-- target track/album/artist has appeared in the library. Callers
|
|
-- should set ONLY the matched_*_id corresponding to the request's
|
|
-- kind and pass pgtype.UUID{} (Valid: false) for the others —
|
|
-- per-kind one-of-three is the contract, NULL for the others
|
|
-- preserves auditability if the matched row is later evicted.
|
|
UPDATE lidarr_requests
|
|
SET status = 'completed',
|
|
matched_track_id = $2,
|
|
matched_album_id = $3,
|
|
matched_artist_id = $4,
|
|
completed_at = now(),
|
|
updated_at = now()
|
|
WHERE id = $1 AND status = 'approved'
|
|
RETURNING *;
|
|
|
|
-- name: HasNonTerminalRequestForMBID :one
|
|
-- Returns true if any user has a pending/approved/completed request
|
|
-- whose MBID matches at the given level. Used to set the `requested`
|
|
-- flag on /api/lidarr/search responses. Terminal-status (rejected,
|
|
-- failed) rows do not count. The same MBID parameter is checked
|
|
-- against artist/album/track columns based on kind.
|
|
SELECT EXISTS (
|
|
SELECT 1 FROM lidarr_requests
|
|
WHERE status IN ('pending', 'approved', 'completed')
|
|
AND ((kind = 'artist' AND lidarr_artist_mbid = @mbid)
|
|
OR (kind = 'album' AND lidarr_album_mbid = @mbid)
|
|
OR (kind = 'track' AND lidarr_track_mbid = @mbid))
|
|
);
|
|
|
|
-- name: GetNonTerminalRequestForMBID :one
|
|
-- Returns the oldest non-terminal (pending/approved/completed) request
|
|
-- whose own-kind MBID matches @mbid, or pgx.ErrNoRows when none. Create()
|
|
-- uses this to dedupe: a re-request for something already in flight
|
|
-- returns the existing row instead of inserting a duplicate. MBIDs are
|
|
-- globally unique per entity type, so the cross-column OR cannot
|
|
-- false-match (an artist MBID never collides with an album/track MBID).
|
|
SELECT * FROM lidarr_requests
|
|
WHERE status IN ('pending', 'approved', 'completed')
|
|
AND ((kind = 'artist' AND lidarr_artist_mbid = @mbid)
|
|
OR (kind = 'album' AND lidarr_album_mbid = @mbid)
|
|
OR (kind = 'track' AND lidarr_track_mbid = @mbid))
|
|
ORDER BY requested_at ASC
|
|
LIMIT 1;
|
|
|
|
-- name: MarkLidarrRequestAddConfirmed :exec
|
|
-- Idempotently records that Lidarr accepted the add for an approved
|
|
-- request. The lidarr_add_confirmed_at IS NULL guard makes a redundant
|
|
-- reconciler retry a no-op rather than bumping updated_at every tick.
|
|
UPDATE lidarr_requests
|
|
SET lidarr_add_confirmed_at = now(),
|
|
updated_at = now()
|
|
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;
|