Files
minstrel/internal/db/queries/reacquisition.sql
T
bvandeusenandClaude Opus 5.5 1d4ef1a23f docs: query comments say what each query selects and why, not how it came to be (#6277)
Rewrites the internal/db/queries comments to rule 32 and regenerates
dbq, whose doc comments and embedded SQL carry them. The bugs behind the
tiered mixes, the md5 order seed, the score bands and the round-robin
arms are restated as the constraint each one enforces; counts from one
library and stale cross-references are gone.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-23 12:31:13 -04:00

94 lines
4.4 KiB
SQL

-- Re-acquisition of missing files.
-- The unit is the album: an album whose files went missing becomes a want for
-- its release group, and the search schedule looks for it.
-- name: GetReacquisitionSettings :one
SELECT * FROM reacquisition_settings WHERE id = true;
-- name: UpdateReacquisitionSettings :one
-- Whole-row write from the admin card; the CHECKs in migration 0056 are the
-- validation, so a bad value fails loudly rather than being clamped silently.
UPDATE reacquisition_settings
SET enabled = sqlc.arg(enabled),
grace_hours = sqlc.arg(grace_hours),
max_per_pass = sqlc.arg(max_per_pass)
WHERE id = true
RETURNING *;
-- name: ListAlbumsDueReacquisition :many
-- The sweeper's selection. An album qualifies when:
--
-- * it still has at least one track whose file has been missing longer than
-- the grace window. Measured on missing_since, which reconcile never
-- re-stamps, so it is a genuine "gone since" clock;
-- * MusicBrainz can name it: the artist has an MBID, and the album a
-- release MBID or a release group. The release MBID is only ever used to
-- find the group, and an album matched to a group may carry no release
-- id. Albums failing this are counted separately
-- (CountAlbumsMissingWithoutMbid);
-- * it is on the wanted list: an album taken off the list, or
-- dropped into the library by hand, is not fetched back;
-- * no want already covers it: none open, and none held since its files
-- went missing. A want held after the loss means the library has a full
-- copy despite the missing rows, so asking again would loop.
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.name AS artist_name,
artists.mbid AS artist_mbid,
COUNT(tracks.id)::bigint AS missing_track_count,
MAX(tracks.missing_since)::timestamptz AS last_missing_since
FROM albums
JOIN artists ON artists.id = albums.artist_id
JOIN tracks ON tracks.album_id = albums.id
WHERE tracks.missing_since IS NOT NULL
AND tracks.missing_since <= now() - make_interval(hours => sqlc.arg(grace_hours)::int)
AND (albums.mbid IS NOT NULL OR albums.release_group_mbid IS NOT NULL)
AND artists.mbid IS NOT NULL
GROUP BY albums.id, albums.title, albums.mbid, albums.release_group_mbid,
artists.name, artists.mbid
HAVING EXISTS (
SELECT 1 FROM wants w
WHERE w.album_id = albums.id OR w.release_group_mbid = albums.release_group_mbid)
AND NOT EXISTS (
SELECT 1 FROM wants w
WHERE (w.album_id = albums.id OR w.release_group_mbid = albums.release_group_mbid)
AND (w.fulfilled_at IS NULL OR w.fulfilled_at > MAX(tracks.missing_since)))
ORDER BY MIN(tracks.missing_since), albums.sort_title
LIMIT sqlc.arg(page_limit);
-- name: CountAlbumsMissingWithoutMbid :one
-- Albums with missing files that can never be wanted automatically because
-- nothing identifies them to MusicBrainz. Surfaced on the admin card so the
-- gap is visible: silently doing nothing for these would read as broken.
SELECT COUNT(DISTINCT albums.id)::bigint
FROM albums
JOIN artists ON artists.id = albums.artist_id
JOIN tracks ON tracks.album_id = albums.id
WHERE tracks.missing_since IS NOT NULL
AND ((albums.mbid IS NULL AND albums.release_group_mbid IS NULL) OR artists.mbid IS NULL);
-- name: WantMissingAlbum :one
-- Records an album with missing files as wanted. A held want for the same
-- group is reopened; an open one is left as it is, and no row comes back.
INSERT INTO wants (release_group_mbid, artist_mbid, artist_name, title, reason, album_id)
VALUES (sqlc.arg(release_group_mbid), sqlc.arg(artist_mbid), sqlc.arg(artist_name),
sqlc.arg(title), 'missing', sqlc.arg(album_id))
ON CONFLICT (release_group_mbid) DO UPDATE
SET reason = 'missing',
album_id = EXCLUDED.album_id,
wanted_at = now(),
fulfilled_at = NULL,
updated_at = now()
WHERE wants.fulfilled_at IS NOT NULL
RETURNING *;
-- name: GetWantsForAlbums :many
-- What the wanted list says about each album on the missing-files page.
SELECT a.id AS album_id, w.id AS want_id, w.wanted_at, w.fulfilled_at
FROM albums a
JOIN wants w ON w.album_id = a.id OR w.release_group_mbid = a.release_group_mbid
WHERE a.id = ANY(sqlc.arg(album_ids)::uuid[])
ORDER BY w.wanted_at DESC;