-- A Request is a persistent "I want this", stored as a MusicBrainz ID -- and almost nothing else. It outlives every download attempt made on -- its behalf: nothing being findable today is the normal case for -- obscure music, and the correct response is to try again next week, -- not to show the user a failed row they have to remember to retry. -- -- Because a Request is only an MBID, it stays true when everything -- around it changes: the explore index is rebuilt, a provider is -- swapped out, the release the user originally saw is superseded by a -- remaster. The display fields are a cache for the list view and are -- never consulted for matching. CREATE TABLE IF NOT EXISTS download_requests ( id INTEGER PRIMARY KEY AUTOINCREMENT, mbid TEXT NOT NULL, entity TEXT NOT NULL CHECK(entity IN ('artist', 'release-group', 'release', 'recording')), library_id INTEGER NOT NULL, -- Display text, cached so the list renders without touching the -- explore index. Neither is authoritative; the MBID is. artist TEXT NOT NULL DEFAULT '', title TEXT NOT NULL DEFAULT '', scope TEXT NOT NULL DEFAULT 'future' CHECK(scope IN ('future', 'all')), -- secondary controls whether an artist request's expansion includes -- compilations, live albums and remixes. Off by default: someone -- subscribing to an artist wants the albums, not six versions of -- the same greatest-hits package. secondary INTEGER NOT NULL DEFAULT 0, state TEXT NOT NULL DEFAULT 'wanted' CHECK(state IN ('wanted', 'satisfied', 'paused')), -- parent_id links a request the reconciler derived from an artist -- request. Deleting the artist takes its derived children with -- it, but children the user pinned themselves have no parent and -- stay. parent_id INTEGER, -- Retry bookkeeping. attempts drives the backoff; last_error is -- the most recent reason it did not work out, which for a request -- is information rather than a failure. attempts INTEGER NOT NULL DEFAULT 0, last_error TEXT NOT NULL DEFAULT '', last_tried_at DATETIME, next_try_at DATETIME, -- external_ids maps provider row ID to that provider's own -- identifier for this request, for clients that keep their own -- persistent list (a Lidarr artist ID). JSON object. external_ids TEXT NOT NULL DEFAULT '{}', created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, -- One request per thing per library. Asking twice is not two -- requests, and this is what lets an artist expansion re-run every -- reconcile without accumulating duplicates. UNIQUE(mbid, library_id), FOREIGN KEY(library_id) REFERENCES libraries(id) ON DELETE CASCADE, FOREIGN KEY(parent_id) REFERENCES download_requests(id) ON DELETE CASCADE ); CREATE INDEX IF NOT EXISTS idx_download_requests_due ON download_requests(state, next_try_at); CREATE INDEX IF NOT EXISTS idx_download_requests_entity ON download_requests(entity, state); CREATE INDEX IF NOT EXISTS idx_download_requests_parent ON download_requests(parent_id) WHERE parent_id IS NOT NULL;