From a86897b35ea0eb61b4fc448597384d2e2af958de Mon Sep 17 00:00:00 2001 From: Bryan Van Deusen Date: Wed, 6 May 2026 12:24:36 -0400 Subject: [PATCH] =?UTF-8?q?feat(db/m7-cover-sources):=20migration=200018?= =?UTF-8?q?=20=E2=80=94=20artist=20art=20+=20provider=20settings?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds the schema for the pluggable cover-art provider abstraction: - Extends albums.cover_art_source CHECK to accept 'theaudiodb' (the constraint from migration 0016 only allowed embedded/sidecar/mbcaa/ none, which would block writes from the new provider). - Adds artist_thumb_path / artist_fanart_path / artist_art_source on artists, with a parallel CHECK constraint and source index. - Adds *_sources_version stamps on both albums and artists for the per-row recheck eligibility logic. Default 0 so every existing row becomes stale relative to the seeded current_version=1, retrying through the new chain on first scan after migrate. - New cover_art_provider_settings table (per-provider enabled / api_key / display_order) and cover_art_sources_meta singleton holding current_version. Seeds both v1 providers (mbcaa + theaudiodb) as enabled. - New artist_art_enrich jsonb column on scan_runs for the 4th scan-orchestrator stage tally. The seed leaves theaudiodb.api_key NULL; the application supplies the upstream's documented test key (2) as the default when the column is NULL, per the no-coercive-settings principle. --- ..._artist_art_and_provider_settings.down.sql | 26 ++++++++ ...18_artist_art_and_provider_settings.up.sql | 62 +++++++++++++++++++ 2 files changed, 88 insertions(+) create mode 100644 internal/db/migrations/0018_artist_art_and_provider_settings.down.sql create mode 100644 internal/db/migrations/0018_artist_art_and_provider_settings.up.sql diff --git a/internal/db/migrations/0018_artist_art_and_provider_settings.down.sql b/internal/db/migrations/0018_artist_art_and_provider_settings.down.sql new file mode 100644 index 00000000..fae6f46c --- /dev/null +++ b/internal/db/migrations/0018_artist_art_and_provider_settings.down.sql @@ -0,0 +1,26 @@ +-- Reverse of 0018. + +ALTER TABLE scan_runs DROP COLUMN IF EXISTS artist_art_enrich; + +DROP TABLE IF EXISTS cover_art_sources_meta; +DROP TABLE IF EXISTS cover_art_provider_settings; + +ALTER TABLE artists DROP COLUMN IF EXISTS artist_art_sources_version; +ALTER TABLE albums DROP COLUMN IF EXISTS cover_art_sources_version; + +DROP INDEX IF EXISTS artists_artist_art_source_idx; +ALTER TABLE artists DROP CONSTRAINT IF EXISTS artists_artist_art_source_check; +ALTER TABLE artists DROP COLUMN IF EXISTS artist_art_source; +ALTER TABLE artists DROP COLUMN IF EXISTS artist_fanart_path; +ALTER TABLE artists DROP COLUMN IF EXISTS artist_thumb_path; + +-- Restore the original albums.cover_art_source CHECK from migration 0016. +ALTER TABLE albums DROP CONSTRAINT IF EXISTS albums_cover_art_source_check; +ALTER TABLE albums + ADD CONSTRAINT albums_cover_art_source_check + CHECK (cover_art_source IS NULL + OR cover_art_source IN ('embedded','sidecar','mbcaa','none')); +-- Note: rows with cover_art_source='theaudiodb' will be rejected by this +-- restored constraint. If down-migrating from a populated DB, run: +-- UPDATE albums SET cover_art_source = NULL WHERE cover_art_source = 'theaudiodb'; +-- before applying this migration. diff --git a/internal/db/migrations/0018_artist_art_and_provider_settings.up.sql b/internal/db/migrations/0018_artist_art_and_provider_settings.up.sql new file mode 100644 index 00000000..37dd3203 --- /dev/null +++ b/internal/db/migrations/0018_artist_art_and_provider_settings.up.sql @@ -0,0 +1,62 @@ +-- M7 cover-sources: schema for additional cover-art providers (TheAudioDB +-- as the v1 implementation), artist art (thumb + fanart), and the +-- recheck-on-source-change trigger. + +-- (0) Extend the existing albums.cover_art_source CHECK to accept the +-- new 'theaudiodb' value. The constraint was created in migration 0016 +-- with the IN list ('embedded','sidecar','mbcaa','none'); without this +-- extension, the enricher's UPDATE setting cover_art_source='theaudiodb' +-- would fail with a CHECK violation. +ALTER TABLE albums DROP CONSTRAINT IF EXISTS albums_cover_art_source_check; +ALTER TABLE albums + ADD CONSTRAINT albums_cover_art_source_check + CHECK (cover_art_source IS NULL + OR cover_art_source IN ('embedded','sidecar','mbcaa','theaudiodb','none')); + +-- (1) Artist art columns parallel albums.cover_art_*. +ALTER TABLE artists + ADD COLUMN artist_thumb_path text, + ADD COLUMN artist_fanart_path text, + ADD COLUMN artist_art_source text; + +ALTER TABLE artists + ADD CONSTRAINT artists_artist_art_source_check + CHECK (artist_art_source IS NULL + OR artist_art_source IN ('theaudiodb','none')); + +CREATE INDEX artists_artist_art_source_idx ON artists (artist_art_source); + +-- (2) Recheck-trigger version stamps. Default 0; current_version starts +-- at 1, so every existing row is "stale" relative to current — first +-- scan after migrate retries every settled row through the new chain. +ALTER TABLE albums + ADD COLUMN cover_art_sources_version int NOT NULL DEFAULT 0; +ALTER TABLE artists + ADD COLUMN artist_art_sources_version int NOT NULL DEFAULT 0; + +-- (3) Per-provider settings + singleton meta row. +CREATE TABLE cover_art_provider_settings ( + provider_id text PRIMARY KEY, + enabled boolean NOT NULL DEFAULT true, + api_key text, + display_order int NOT NULL DEFAULT 0, + created_at timestamptz NOT NULL DEFAULT now(), + updated_at timestamptz NOT NULL DEFAULT now() +); + +CREATE TABLE cover_art_sources_meta ( + id boolean PRIMARY KEY DEFAULT true, + current_version int NOT NULL DEFAULT 1, + CONSTRAINT cover_art_sources_meta_singleton CHECK (id = true) +); +INSERT INTO cover_art_sources_meta (id, current_version) VALUES (true, 1); + +-- Seed both v1 providers as enabled. TheAudioDB's api_key stays NULL; +-- the application supplies the test key '2' when the column is NULL, +-- per the no-coercive-settings principle. +INSERT INTO cover_art_provider_settings (provider_id, enabled, display_order) VALUES + ('mbcaa', true, 0), + ('theaudiodb', true, 1); + +-- (4) Scan-runs gains a stage tally column for artist art enrichment. +ALTER TABLE scan_runs ADD COLUMN artist_art_enrich jsonb;