Files
yellowjacket/backend/database/sql/queries/download.sql
T
logan 62bb40fc4d fix(download): make "check now" actually check now, and say what it did
The button ran a normal reconcile pass, which honours each request's
retry backoff — so a request searched an hour ago was not due, nothing
was searched, and the button looked broken. The backoff is a promise to
the providers, not to the user: a person pressing "check now" *is* the
schedule, so a user-initiated pass ignores it and the loop still does
not.

"Nothing happened" also needed a reason. Summary now carries how many
requests are still being looked for and whether any download client is
enabled at all, which is the one cause of silence the user can fix —
and the requests tab says so above the list rather than leaving an
inert list to be interpreted.

The rest is the retry schedule finally being admitted to: rows show
when the next check falls due, "Looking for" explains that a request
sitting there is waiting rather than failing, and the page header says
how often the list is worked.
2026-08-11 01:15:23 -04:00

222 lines
7.2 KiB
SQL

-- name: ListDownloadProviders :many
SELECT id, kind, name, enabled, priority, settings, created_at
FROM download_providers
ORDER BY priority DESC, name;
-- name: GetDownloadProvider :one
SELECT id, kind, name, enabled, priority, settings, created_at
FROM download_providers
WHERE id = ?;
-- name: CreateDownloadProvider :one
INSERT INTO download_providers (kind, name, enabled, priority, settings)
VALUES (?, ?, ?, ?, ?)
RETURNING id;
-- name: UpdateDownloadProvider :exec
UPDATE download_providers
SET name = ?, enabled = ?, priority = ?, settings = ?
WHERE id = ?;
-- name: DeleteDownloadProvider :exec
DELETE FROM download_providers
WHERE id = ?;
-- ---------------------------------------------------------------------
-- Downloads (one-shot search+grab attempts)
-- ---------------------------------------------------------------------
-- name: CreateDownload :exec
INSERT INTO download_downloads (
id, library_id, source, request_id, release_mbid, release_group_mbid,
recording_mbid, artist, album, query, expected, state
)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);
-- name: GetDownload :one
SELECT id, library_id, source, request_id, release_mbid, release_group_mbid,
recording_mbid, artist, album, query, expected, state, error,
created_at, updated_at
FROM download_downloads
WHERE id = ?;
-- name: ListDownloads :many
SELECT id, library_id, source, request_id, release_mbid, release_group_mbid,
recording_mbid, artist, album, query, expected, state, error,
created_at, updated_at
FROM download_downloads
ORDER BY created_at DESC
LIMIT ?;
-- name: ListLiveDownloads :many
SELECT id, library_id, source, request_id, release_mbid, release_group_mbid,
recording_mbid, artist, album, query, expected, state, error,
created_at, updated_at
FROM download_downloads
WHERE state NOT IN ('complete', 'cancelled', 'failed')
ORDER BY created_at;
-- name: SetDownloadState :exec
UPDATE download_downloads
SET state = ?, error = ?, updated_at = CURRENT_TIMESTAMP
WHERE id = ?;
-- name: DeleteDownload :exec
DELETE FROM download_downloads
WHERE id = ?;
-- name: DeleteFinishedDownloads :exec
DELETE FROM download_downloads
WHERE state IN ('complete', 'cancelled', 'failed');
-- ---------------------------------------------------------------------
-- Items (transfer records within a download)
-- ---------------------------------------------------------------------
-- name: CreateDownloadItem :exec
INSERT INTO download_items (
id, download_id, provider_id, transport_id, external_id,
candidate, state, staging_dir, bytes_total
)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?);
-- name: GetDownloadItem :one
SELECT id, download_id, provider_id, transport_id, external_id, candidate,
state, staging_dir, bytes_done, bytes_total, imported_paths,
error, created_at, updated_at
FROM download_items
WHERE id = ?;
-- name: ListDownloadItemsForDownload :many
SELECT id, download_id, provider_id, transport_id, external_id, candidate,
state, staging_dir, bytes_done, bytes_total, imported_paths,
error, created_at, updated_at
FROM download_items
WHERE download_id = ?
ORDER BY created_at;
-- name: ListLiveDownloadItems :many
SELECT id, download_id, provider_id, transport_id, external_id, candidate,
state, staging_dir, bytes_done, bytes_total, imported_paths,
error, created_at, updated_at
FROM download_items
WHERE state NOT IN ('complete', 'cancelled', 'failed')
ORDER BY created_at;
-- name: SetDownloadItemState :exec
UPDATE download_items
SET state = ?, error = ?, updated_at = CURRENT_TIMESTAMP
WHERE id = ?;
-- name: SetDownloadItemProgress :exec
UPDATE download_items
SET bytes_done = ?, bytes_total = ?, updated_at = CURRENT_TIMESTAMP
WHERE id = ?;
-- name: SetDownloadItemExternalID :exec
UPDATE download_items
SET external_id = ?, updated_at = CURRENT_TIMESTAMP
WHERE id = ?;
-- name: SetDownloadItemImported :exec
UPDATE download_items
SET imported_paths = ?, state = 'complete', error = '',
updated_at = CURRENT_TIMESTAMP
WHERE id = ?;
-- ---------------------------------------------------------------------
-- Requests (durable "I asked for this" records)
-- ---------------------------------------------------------------------
-- name: UpsertDownloadRequest :one
-- Adding something already requested is not an error and must not
-- reset the retry clock, so the conflict path only refreshes display
-- text and un-pauses nothing. scope and secondary are updated because
-- asking again with a wider scope is a real change of intent.
INSERT INTO download_requests (
mbid, entity, library_id, artist, title, scope, secondary,
parent_id, next_try_at
)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, CURRENT_TIMESTAMP)
ON CONFLICT(mbid, library_id) DO UPDATE SET
artist = CASE WHEN excluded.artist <> '' THEN excluded.artist
ELSE download_requests.artist END,
title = CASE WHEN excluded.title <> '' THEN excluded.title
ELSE download_requests.title END,
scope = excluded.scope,
secondary = excluded.secondary,
updated_at = CURRENT_TIMESTAMP
RETURNING id;
-- name: GetDownloadRequest :one
SELECT * FROM download_requests WHERE id = ?;
-- name: GetDownloadRequestByMBID :one
SELECT * FROM download_requests WHERE mbid = ? AND library_id = ?;
-- name: ListDownloadRequests :many
SELECT * FROM download_requests
ORDER BY
CASE state WHEN 'wanted' THEN 0 WHEN 'paused' THEN 1 ELSE 2 END,
artist, title;
-- name: ListDownloadRequestsByEntity :many
SELECT * FROM download_requests
WHERE entity = ? AND state = ?
ORDER BY id;
-- name: ListDueDownloadRequests :many
-- Everything the reconciler should act on this pass: wanted, not an
-- artist subscription (those expand rather than download), and either
-- never tried or past its backoff.
SELECT * FROM download_requests
WHERE state = 'wanted'
AND entity <> 'artist'
AND (next_try_at IS NULL OR next_try_at <= CURRENT_TIMESTAMP)
ORDER BY attempts, created_at
LIMIT ?;
-- name: ListWantedDownloadRequests :many
-- The same set ignoring the backoff, for a pass the user asked for by
-- hand: "check now" that respected a six-hour retry schedule looked
-- like a button that did nothing.
SELECT * FROM download_requests
WHERE state = 'wanted'
AND entity <> 'artist'
ORDER BY attempts, created_at
LIMIT ?;
-- name: ListChildDownloadRequests :many
SELECT * FROM download_requests WHERE parent_id = ? ORDER BY id;
-- name: SetDownloadRequestState :exec
UPDATE download_requests
SET state = ?, last_error = ?, updated_at = CURRENT_TIMESTAMP
WHERE id = ?;
-- name: RecordDownloadRequestAttempt :exec
UPDATE download_requests
SET attempts = attempts + 1,
last_error = ?,
last_tried_at = CURRENT_TIMESTAMP,
next_try_at = ?,
updated_at = CURRENT_TIMESTAMP
WHERE id = ?;
-- name: SatisfyDownloadRequest :exec
UPDATE download_requests
SET state = 'satisfied', last_error = '', next_try_at = NULL,
updated_at = CURRENT_TIMESTAMP
WHERE id = ?;
-- name: SetDownloadRequestExternalIDs :exec
UPDATE download_requests
SET external_ids = ?, updated_at = CURRENT_TIMESTAMP
WHERE id = ?;
-- name: DeleteDownloadRequest :exec
DELETE FROM download_requests WHERE id = ?;
-- name: DeleteSatisfiedDownloadRequests :exec
DELETE FROM download_requests WHERE state = 'satisfied';