release / govulncheck (push) Successful in 17s
release / web (push) Successful in 1m33s
release / go (push) Successful in 1m49s
release / integration (push) Successful in 5m42s
release / android (push) Successful in 5m59s
release / Build signed APK (releases and dev) (push) Successful in 6m9s
release / Attach APK to the Release (tag releases only) (push) Skipped
release / Build + push container image (push) Successful in 16s
release / Verify release artifacts (tag releases only) (push) Skipped
Applies rule 32's migration exception: each header still says what the schema was, what changes and what it prevents, but task, milestone, decision and rule ids are replaced by the practice they stood for, the operator quotes by the decision, single-install counts are dropped, and pointers to a deleted package and an external design doc are gone. golang-migrate keeps no checksum, so editing applied migrations' comments is safe. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
70 lines
3.6 KiB
SQL
70 lines
3.6 KiB
SQL
-- 0069_acoustid_lookup.up.sql — recording MBIDs looked up through AcoustID
|
|
-- for tracks whose tags carry none.
|
|
--
|
|
-- A track with no recording MBID is invisible to the ListenBrainz similarity
|
|
-- arm in both directions, so this fills the ids the tags leave empty.
|
|
|
|
-- Where tracks.mbid came from. The file's own tag always outranks a lookup:
|
|
-- the scan's upsert keeps a looked-up id while the tag carries
|
|
-- none, and replaces it the moment the tag carries one.
|
|
ALTER TABLE tracks ADD COLUMN mbid_source text;
|
|
-- Every id stored so far was read from a tag (the scan or the tag backfill),
|
|
-- or inherited from a merged duplicate's tag.
|
|
UPDATE tracks SET mbid_source = 'tag' WHERE mbid IS NOT NULL;
|
|
ALTER TABLE tracks
|
|
ADD CONSTRAINT tracks_mbid_source_check CHECK (mbid_source IN ('tag', 'acoustid')),
|
|
ADD CONSTRAINT tracks_mbid_source_pair CHECK ((mbid IS NULL) = (mbid_source IS NULL));
|
|
|
|
-- What happened the last time a track was looked up. A table of its own, as
|
|
-- track_loudness is (0065): tracks is read with SELECT * on the hot path.
|
|
--
|
|
-- What a row means, which the lookup worker depends on:
|
|
-- no row never looked up, or the file changed since (the scan deletes
|
|
-- the row): look it up
|
|
-- matched one recording cleared the score threshold, or one was left
|
|
-- after disambiguating by title and length; recording_mbid is it
|
|
-- ambiguous several recordings cleared it and nothing told them apart.
|
|
-- Nothing is written: a wrong MBID would feed similarity the
|
|
-- wrong neighbours, which is worse than none
|
|
-- no_match AcoustID linked nothing at or above the threshold
|
|
-- failed fpcalc rejected the file, or AcoustID rejected its print
|
|
-- Every state is settled until the file changes. A failure that says nothing
|
|
-- about the file (AcoustID unreachable, a timeout, a cancelled pass) writes no
|
|
-- row, so the worker tries again.
|
|
CREATE TABLE track_acoustid_lookups (
|
|
track_id uuid PRIMARY KEY REFERENCES tracks (id) ON DELETE CASCADE,
|
|
state text NOT NULL,
|
|
-- The best score any linked recording had; NULL when none was linked.
|
|
best_score real,
|
|
-- How many distinct recordings were linked, at any score.
|
|
candidates integer NOT NULL DEFAULT 0,
|
|
recording_mbid text,
|
|
-- Why a lookup failed, for the admin list.
|
|
detail text,
|
|
looked_up_at timestamptz NOT NULL DEFAULT now(),
|
|
|
|
CONSTRAINT track_acoustid_lookups_state_check
|
|
CHECK (state IN ('matched', 'ambiguous', 'no_match', 'failed')),
|
|
CONSTRAINT track_acoustid_lookups_matched_has_mbid
|
|
CHECK ((state = 'matched') = (recording_mbid IS NOT NULL))
|
|
);
|
|
CREATE INDEX track_acoustid_lookups_state ON track_acoustid_lookups (state);
|
|
|
|
-- AcoustID's knobs, in admin Settings. Singleton in the style of
|
|
-- loudness_settings (0065).
|
|
CREATE TABLE acoustid_settings (
|
|
id boolean PRIMARY KEY DEFAULT true,
|
|
-- Off by default: AcoustID needs a key an admin registers, and the lookup
|
|
-- sends fingerprints to a third party.
|
|
enabled boolean NOT NULL DEFAULT false,
|
|
api_key text,
|
|
-- The score a recording needs before it is considered at all. AcoustID
|
|
-- scores a true match close to 1; 0.85 leaves room for a lossy encode.
|
|
min_score real NOT NULL DEFAULT 0.85,
|
|
updated_at timestamptz NOT NULL DEFAULT now(),
|
|
|
|
CONSTRAINT acoustid_settings_singleton CHECK (id = true),
|
|
CONSTRAINT acoustid_settings_min_score_range CHECK (min_score >= 0.5 AND min_score <= 1)
|
|
);
|
|
INSERT INTO acoustid_settings (id) VALUES (true) ON CONFLICT (id) DO NOTHING;
|