-- name: UpsertTrackLoudness :exec -- Written when the backfill measures a track (#4995). Replaces the row -- wholesale: a measurement of the old bytes has no standing once the file has -- changed. INSERT INTO track_loudness ( track_id, integrated_lufs, true_peak_dbtp, loudness_range_lu, block_hist_start, block_hist, unreadable, analysis_version ) VALUES ( sqlc.arg(track_id), sqlc.narg(integrated_lufs), sqlc.narg(true_peak_dbtp), sqlc.narg(loudness_range_lu), sqlc.narg(block_hist_start), sqlc.narg(block_hist), sqlc.arg(unreadable), sqlc.arg(analysis_version) ) ON CONFLICT (track_id) DO UPDATE SET integrated_lufs = EXCLUDED.integrated_lufs, true_peak_dbtp = EXCLUDED.true_peak_dbtp, loudness_range_lu = EXCLUDED.loudness_range_lu, block_hist_start = EXCLUDED.block_hist_start, block_hist = EXCLUDED.block_hist, unreadable = EXCLUDED.unreadable, analysis_version = EXCLUDED.analysis_version, analyzed_at = now(); -- name: DeleteTrackLoudness :exec -- The scan saw new bytes at this path. The stored measurement describes the old -- ones, so it goes, and the backfill measures the file again. DELETE FROM track_loudness WHERE track_id = $1; -- name: ListTracksNeedingLoudness :many -- The backfill's work queue: tracks with no measurement, or one taken by an -- older method. Keyset-paged on id so a pass visits each track at most once; -- an inconclusive attempt writes no row, and without the cursor a file that -- keeps timing out would be listed again straight away. Missing tracks are -- skipped: there is no file to read. SELECT t.id, t.file_path, t.duration_ms FROM tracks t LEFT JOIN track_loudness l ON l.track_id = t.id WHERE t.missing_since IS NULL AND (l.track_id IS NULL OR l.analysis_version < sqlc.arg(current_version)) AND t.id > sqlc.arg(after_id) ORDER BY t.id LIMIT sqlc.arg(batch_limit); -- name: GetLoudnessCoverage :one -- The admin gauge. measured + silent + unreadable + pending = total. Missing -- tracks are excluded, or the gauge could never reach the end. SELECT count(*)::bigint AS total, count(*) FILTER ( WHERE l.analysis_version >= sqlc.arg(current_version) AND l.integrated_lufs IS NOT NULL )::bigint AS measured, count(*) FILTER ( WHERE l.analysis_version >= sqlc.arg(current_version) AND l.integrated_lufs IS NULL AND NOT l.unreadable )::bigint AS silent, count(*) FILTER ( WHERE l.analysis_version >= sqlc.arg(current_version) AND l.unreadable )::bigint AS unreadable, count(*) FILTER ( WHERE l.track_id IS NULL OR l.analysis_version < sqlc.arg(current_version) )::bigint AS pending FROM tracks t LEFT JOIN track_loudness l ON l.track_id = t.id WHERE t.missing_since IS NULL; -- name: GetLoudnessSettings :one SELECT * FROM loudness_settings WHERE id = true; -- name: UpdateLoudnessSettings :one -- Whole-row write from the admin card; migration 0065's CHECK is the backstop -- behind the service's own validation. UPDATE loudness_settings SET enabled = sqlc.arg(enabled), backfill_concurrency = sqlc.arg(backfill_concurrency), updated_at = now() WHERE id = true RETURNING *; -- name: ListAlbumsNeedingLoudness :many -- The album pass's work queue (#4996): albums whose present tracks or their -- measurements have changed since album loudness was last computed, or that -- never had it. The digest is over every present track's id and the -- measurement it holds at the current version ('-' for none), so a track -- joining, leaving or being re-measured changes it. Keyset-paged on album id -- so a pass ends even if storing one album keeps failing. WITH present AS ( SELECT t.album_id, md5(string_agg( t.id::text || ':' || coalesce( l.analysis_version::text || '@' || l.analyzed_at::text, '-'), ',' ORDER BY t.id)) AS digest FROM tracks t LEFT JOIN track_loudness l ON l.track_id = t.id AND l.analysis_version >= sqlc.arg(current_version)::smallint WHERE t.missing_since IS NULL GROUP BY t.album_id ) SELECT c.album_id, c.digest::text AS digest FROM present c LEFT JOIN album_loudness a ON a.album_id = c.album_id WHERE (a.album_id IS NULL OR a.inputs_digest <> c.digest) -- Casts: sqlc cannot infer a parameter's type through a CTE alias. AND c.album_id > sqlc.arg(after_id)::uuid ORDER BY c.album_id LIMIT sqlc.arg(batch_limit)::integer; -- name: ListAlbumLoudnessInputs :many -- Every present track on one album with its current measurement, if any. -- settled is false for a track not yet measured at the current version. SELECT t.id, (l.track_id IS NOT NULL)::boolean AS settled, l.true_peak_dbtp, l.block_hist_start, l.block_hist FROM tracks t LEFT JOIN track_loudness l ON l.track_id = t.id AND l.analysis_version >= sqlc.arg(current_version) WHERE t.album_id = sqlc.arg(album_id) AND t.missing_since IS NULL; -- name: UpsertAlbumLoudness :exec INSERT INTO album_loudness ( album_id, integrated_lufs, true_peak_dbtp, tracks_total, tracks_settled, inputs_digest ) VALUES ( sqlc.arg(album_id), sqlc.narg(integrated_lufs), sqlc.narg(true_peak_dbtp), sqlc.arg(tracks_total), sqlc.arg(tracks_settled), sqlc.arg(inputs_digest) ) ON CONFLICT (album_id) DO UPDATE SET integrated_lufs = EXCLUDED.integrated_lufs, true_peak_dbtp = EXCLUDED.true_peak_dbtp, tracks_total = EXCLUDED.tracks_total, tracks_settled = EXCLUDED.tracks_settled, inputs_digest = EXCLUDED.inputs_digest, computed_at = now(); -- name: ListOrphanAlbumLoudness :many -- Album rows whose album has no present track left (every file missing). The -- album row itself survives a missing file, so its loudness would otherwise -- stay behind describing tracks that are gone; it is recomputed if they return. SELECT a.album_id FROM album_loudness a WHERE NOT EXISTS ( SELECT 1 FROM tracks t WHERE t.album_id = a.album_id AND t.missing_since IS NULL ); -- name: DeleteAlbumLoudness :exec DELETE FROM album_loudness WHERE album_id = ANY(sqlc.arg(album_ids)::uuid[]); -- name: GetAlbumLoudness :one -- The stored album values, read before a recompute so a sync change is -- logged only when they actually move. SELECT integrated_lufs, true_peak_dbtp FROM album_loudness WHERE album_id = $1; -- name: GetReplayGainByTrackIDs :many -- Track and album loudness for a set of tracks, for every surface that hands -- gains to a client (#4997). A measurement from an older analysis version is -- still delivered: it is a better gain than none until the backfill redoes it. SELECT t.id, tl.integrated_lufs AS track_lufs, tl.true_peak_dbtp AS track_peak_dbtp, al.integrated_lufs AS album_lufs, al.true_peak_dbtp AS album_peak_dbtp FROM tracks t LEFT JOIN track_loudness tl ON tl.track_id = t.id LEFT JOIN album_loudness al ON al.album_id = t.album_id WHERE t.id = ANY(sqlc.arg(ids)::uuid[]); -- name: GetAlbumLoudnessByIDs :many SELECT album_id, integrated_lufs, true_peak_dbtp FROM album_loudness WHERE album_id = ANY(sqlc.arg(ids)::uuid[]);