feat(db/m7-cover-sources): SQL queries for provider settings + recheck

- Extends GetAlbumCoverageRollup's with_art FILTER to include
  'theaudiodb' so F's coverage gauge surfaces TheAudioDB-found rows
  as with_art rather than silently undercounting.
- Modifies ListAlbumsMissingCover to take the current sources_version
  as a parameter; eligibility now includes stale-'none' rows.
- Adds SetAlbumCoverWithVersion (atomic write of path + source +
  version stamp) and the parallel SetArtistArtWithVersion +
  ClearArtistArtNone + ListArtistsMissingArt for the artist-art
  enricher.
- New coverart_settings.sql with ListProviderSettings,
  UpsertProviderSettings (boot reconciliation, preserves operator
  values on conflict), UpdateProviderSettings (admin PATCH; tri-
  state api_key handling), GetCurrentSourcesVersion,
  BumpSourcesVersion (RETURNING the new value).
This commit is contained in:
2026-05-06 12:28:18 -04:00
parent a86897b35e
commit 526a78b302
12 changed files with 550 additions and 88 deletions
+18 -21
View File
@@ -109,41 +109,38 @@ func (q *Queries) GetAlbumWithFirstTrackPath(ctx context.Context, id pgtype.UUID
const listAlbumsMissingCover = `-- name: ListAlbumsMissingCover :many
SELECT a.id, a.mbid, a.title, a.artist_id
SELECT a.id
FROM albums a
WHERE a.cover_art_source IS NULL
ORDER BY a.created_at ASC
LIMIT $1
OR (a.cover_art_source = 'none' AND a.cover_art_sources_version != $1)
ORDER BY a.created_at
LIMIT $2
`
type ListAlbumsMissingCoverRow struct {
ID pgtype.UUID
Mbid *string
Title string
ArtistID pgtype.UUID
type ListAlbumsMissingCoverParams struct {
CoverArtSourcesVersion int32
Limit int32
}
// M7 #353: album cover enrichment queries.
// Albums where cover_art_source has never been set. Used by the boot
// backfill and post-scan enrichment passes. LIMIT supplied by caller.
func (q *Queries) ListAlbumsMissingCover(ctx context.Context, limit int32) ([]ListAlbumsMissingCoverRow, error) {
rows, err := q.db.Query(ctx, listAlbumsMissingCover, limit)
// M7 cover-sources: returns rows the enricher should attempt. Eligible:
// cover_art_source IS NULL (never tried), OR cover_art_source = 'none'
// AND cover_art_sources_version != current (settled under an older
// source set; recheck against the current chain). LIMIT supplied by
// caller for batching.
func (q *Queries) ListAlbumsMissingCover(ctx context.Context, arg ListAlbumsMissingCoverParams) ([]pgtype.UUID, error) {
rows, err := q.db.Query(ctx, listAlbumsMissingCover, arg.CoverArtSourcesVersion, arg.Limit)
if err != nil {
return nil, err
}
defer rows.Close()
var items []ListAlbumsMissingCoverRow
var items []pgtype.UUID
for rows.Next() {
var i ListAlbumsMissingCoverRow
if err := rows.Scan(
&i.ID,
&i.Mbid,
&i.Title,
&i.ArtistID,
); err != nil {
var id pgtype.UUID
if err := rows.Scan(&id); err != nil {
return nil, err
}
items = append(items, i)
items = append(items, id)
}
if err := rows.Err(); err != nil {
return nil, err