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.
1020 lines
25 KiB
Go
1020 lines
25 KiB
Go
// Code generated by sqlc. DO NOT EDIT.
|
|
// versions:
|
|
// sqlc v1.30.0
|
|
// source: download.sql
|
|
|
|
package sqlcgen
|
|
|
|
import (
|
|
"context"
|
|
"database/sql"
|
|
)
|
|
|
|
const createDownload = `-- 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 (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
`
|
|
|
|
type CreateDownloadParams struct {
|
|
ID string
|
|
LibraryID int64
|
|
Source string
|
|
RequestID sql.NullInt64
|
|
ReleaseMbid sql.NullString
|
|
ReleaseGroupMbid sql.NullString
|
|
RecordingMbid sql.NullString
|
|
Artist string
|
|
Album string
|
|
Query string
|
|
Expected string
|
|
State string
|
|
}
|
|
|
|
// ---------------------------------------------------------------------
|
|
// Downloads (one-shot search+grab attempts)
|
|
// ---------------------------------------------------------------------
|
|
func (q *Queries) CreateDownload(ctx context.Context, arg CreateDownloadParams) error {
|
|
_, err := q.db.ExecContext(ctx, createDownload,
|
|
arg.ID,
|
|
arg.LibraryID,
|
|
arg.Source,
|
|
arg.RequestID,
|
|
arg.ReleaseMbid,
|
|
arg.ReleaseGroupMbid,
|
|
arg.RecordingMbid,
|
|
arg.Artist,
|
|
arg.Album,
|
|
arg.Query,
|
|
arg.Expected,
|
|
arg.State,
|
|
)
|
|
return err
|
|
}
|
|
|
|
const createDownloadItem = `-- name: CreateDownloadItem :exec
|
|
|
|
INSERT INTO download_items (
|
|
id, download_id, provider_id, transport_id, external_id,
|
|
candidate, state, staging_dir, bytes_total
|
|
)
|
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
`
|
|
|
|
type CreateDownloadItemParams struct {
|
|
ID string
|
|
DownloadID string
|
|
ProviderID int64
|
|
TransportID sql.NullInt64
|
|
ExternalID string
|
|
Candidate string
|
|
State string
|
|
StagingDir string
|
|
BytesTotal int64
|
|
}
|
|
|
|
// ---------------------------------------------------------------------
|
|
// Items (transfer records within a download)
|
|
// ---------------------------------------------------------------------
|
|
func (q *Queries) CreateDownloadItem(ctx context.Context, arg CreateDownloadItemParams) error {
|
|
_, err := q.db.ExecContext(ctx, createDownloadItem,
|
|
arg.ID,
|
|
arg.DownloadID,
|
|
arg.ProviderID,
|
|
arg.TransportID,
|
|
arg.ExternalID,
|
|
arg.Candidate,
|
|
arg.State,
|
|
arg.StagingDir,
|
|
arg.BytesTotal,
|
|
)
|
|
return err
|
|
}
|
|
|
|
const createDownloadProvider = `-- name: CreateDownloadProvider :one
|
|
INSERT INTO download_providers (kind, name, enabled, priority, settings)
|
|
VALUES (?, ?, ?, ?, ?)
|
|
RETURNING id
|
|
`
|
|
|
|
type CreateDownloadProviderParams struct {
|
|
Kind string
|
|
Name string
|
|
Enabled int64
|
|
Priority int64
|
|
Settings string
|
|
}
|
|
|
|
func (q *Queries) CreateDownloadProvider(ctx context.Context, arg CreateDownloadProviderParams) (int64, error) {
|
|
row := q.db.QueryRowContext(ctx, createDownloadProvider,
|
|
arg.Kind,
|
|
arg.Name,
|
|
arg.Enabled,
|
|
arg.Priority,
|
|
arg.Settings,
|
|
)
|
|
var id int64
|
|
err := row.Scan(&id)
|
|
return id, err
|
|
}
|
|
|
|
const deleteDownload = `-- name: DeleteDownload :exec
|
|
DELETE FROM download_downloads
|
|
WHERE id = ?
|
|
`
|
|
|
|
func (q *Queries) DeleteDownload(ctx context.Context, id string) error {
|
|
_, err := q.db.ExecContext(ctx, deleteDownload, id)
|
|
return err
|
|
}
|
|
|
|
const deleteDownloadProvider = `-- name: DeleteDownloadProvider :exec
|
|
DELETE FROM download_providers
|
|
WHERE id = ?
|
|
`
|
|
|
|
func (q *Queries) DeleteDownloadProvider(ctx context.Context, id int64) error {
|
|
_, err := q.db.ExecContext(ctx, deleteDownloadProvider, id)
|
|
return err
|
|
}
|
|
|
|
const deleteDownloadRequest = `-- name: DeleteDownloadRequest :exec
|
|
DELETE FROM download_requests WHERE id = ?
|
|
`
|
|
|
|
func (q *Queries) DeleteDownloadRequest(ctx context.Context, id int64) error {
|
|
_, err := q.db.ExecContext(ctx, deleteDownloadRequest, id)
|
|
return err
|
|
}
|
|
|
|
const deleteFinishedDownloads = `-- name: DeleteFinishedDownloads :exec
|
|
DELETE FROM download_downloads
|
|
WHERE state IN ('complete', 'cancelled', 'failed')
|
|
`
|
|
|
|
func (q *Queries) DeleteFinishedDownloads(ctx context.Context) error {
|
|
_, err := q.db.ExecContext(ctx, deleteFinishedDownloads)
|
|
return err
|
|
}
|
|
|
|
const deleteSatisfiedDownloadRequests = `-- name: DeleteSatisfiedDownloadRequests :exec
|
|
DELETE FROM download_requests WHERE state = 'satisfied'
|
|
`
|
|
|
|
func (q *Queries) DeleteSatisfiedDownloadRequests(ctx context.Context) error {
|
|
_, err := q.db.ExecContext(ctx, deleteSatisfiedDownloadRequests)
|
|
return err
|
|
}
|
|
|
|
const getDownload = `-- 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 = ?
|
|
`
|
|
|
|
func (q *Queries) GetDownload(ctx context.Context, id string) (DownloadDownload, error) {
|
|
row := q.db.QueryRowContext(ctx, getDownload, id)
|
|
var i DownloadDownload
|
|
err := row.Scan(
|
|
&i.ID,
|
|
&i.LibraryID,
|
|
&i.Source,
|
|
&i.RequestID,
|
|
&i.ReleaseMbid,
|
|
&i.ReleaseGroupMbid,
|
|
&i.RecordingMbid,
|
|
&i.Artist,
|
|
&i.Album,
|
|
&i.Query,
|
|
&i.Expected,
|
|
&i.State,
|
|
&i.Error,
|
|
&i.CreatedAt,
|
|
&i.UpdatedAt,
|
|
)
|
|
return i, err
|
|
}
|
|
|
|
const getDownloadItem = `-- 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 = ?
|
|
`
|
|
|
|
func (q *Queries) GetDownloadItem(ctx context.Context, id string) (DownloadItem, error) {
|
|
row := q.db.QueryRowContext(ctx, getDownloadItem, id)
|
|
var i DownloadItem
|
|
err := row.Scan(
|
|
&i.ID,
|
|
&i.DownloadID,
|
|
&i.ProviderID,
|
|
&i.TransportID,
|
|
&i.ExternalID,
|
|
&i.Candidate,
|
|
&i.State,
|
|
&i.StagingDir,
|
|
&i.BytesDone,
|
|
&i.BytesTotal,
|
|
&i.ImportedPaths,
|
|
&i.Error,
|
|
&i.CreatedAt,
|
|
&i.UpdatedAt,
|
|
)
|
|
return i, err
|
|
}
|
|
|
|
const getDownloadProvider = `-- name: GetDownloadProvider :one
|
|
SELECT id, kind, name, enabled, priority, settings, created_at
|
|
FROM download_providers
|
|
WHERE id = ?
|
|
`
|
|
|
|
func (q *Queries) GetDownloadProvider(ctx context.Context, id int64) (DownloadProvider, error) {
|
|
row := q.db.QueryRowContext(ctx, getDownloadProvider, id)
|
|
var i DownloadProvider
|
|
err := row.Scan(
|
|
&i.ID,
|
|
&i.Kind,
|
|
&i.Name,
|
|
&i.Enabled,
|
|
&i.Priority,
|
|
&i.Settings,
|
|
&i.CreatedAt,
|
|
)
|
|
return i, err
|
|
}
|
|
|
|
const getDownloadRequest = `-- name: GetDownloadRequest :one
|
|
SELECT id, mbid, entity, library_id, artist, title, scope, secondary, state, parent_id, attempts, last_error, last_tried_at, next_try_at, external_ids, created_at, updated_at FROM download_requests WHERE id = ?
|
|
`
|
|
|
|
func (q *Queries) GetDownloadRequest(ctx context.Context, id int64) (DownloadRequest, error) {
|
|
row := q.db.QueryRowContext(ctx, getDownloadRequest, id)
|
|
var i DownloadRequest
|
|
err := row.Scan(
|
|
&i.ID,
|
|
&i.Mbid,
|
|
&i.Entity,
|
|
&i.LibraryID,
|
|
&i.Artist,
|
|
&i.Title,
|
|
&i.Scope,
|
|
&i.Secondary,
|
|
&i.State,
|
|
&i.ParentID,
|
|
&i.Attempts,
|
|
&i.LastError,
|
|
&i.LastTriedAt,
|
|
&i.NextTryAt,
|
|
&i.ExternalIds,
|
|
&i.CreatedAt,
|
|
&i.UpdatedAt,
|
|
)
|
|
return i, err
|
|
}
|
|
|
|
const getDownloadRequestByMBID = `-- name: GetDownloadRequestByMBID :one
|
|
SELECT id, mbid, entity, library_id, artist, title, scope, secondary, state, parent_id, attempts, last_error, last_tried_at, next_try_at, external_ids, created_at, updated_at FROM download_requests WHERE mbid = ? AND library_id = ?
|
|
`
|
|
|
|
type GetDownloadRequestByMBIDParams struct {
|
|
Mbid string
|
|
LibraryID int64
|
|
}
|
|
|
|
func (q *Queries) GetDownloadRequestByMBID(ctx context.Context, arg GetDownloadRequestByMBIDParams) (DownloadRequest, error) {
|
|
row := q.db.QueryRowContext(ctx, getDownloadRequestByMBID, arg.Mbid, arg.LibraryID)
|
|
var i DownloadRequest
|
|
err := row.Scan(
|
|
&i.ID,
|
|
&i.Mbid,
|
|
&i.Entity,
|
|
&i.LibraryID,
|
|
&i.Artist,
|
|
&i.Title,
|
|
&i.Scope,
|
|
&i.Secondary,
|
|
&i.State,
|
|
&i.ParentID,
|
|
&i.Attempts,
|
|
&i.LastError,
|
|
&i.LastTriedAt,
|
|
&i.NextTryAt,
|
|
&i.ExternalIds,
|
|
&i.CreatedAt,
|
|
&i.UpdatedAt,
|
|
)
|
|
return i, err
|
|
}
|
|
|
|
const listChildDownloadRequests = `-- name: ListChildDownloadRequests :many
|
|
SELECT id, mbid, entity, library_id, artist, title, scope, secondary, state, parent_id, attempts, last_error, last_tried_at, next_try_at, external_ids, created_at, updated_at FROM download_requests WHERE parent_id = ? ORDER BY id
|
|
`
|
|
|
|
func (q *Queries) ListChildDownloadRequests(ctx context.Context, parentID sql.NullInt64) ([]DownloadRequest, error) {
|
|
rows, err := q.db.QueryContext(ctx, listChildDownloadRequests, parentID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer rows.Close()
|
|
var items []DownloadRequest
|
|
for rows.Next() {
|
|
var i DownloadRequest
|
|
if err := rows.Scan(
|
|
&i.ID,
|
|
&i.Mbid,
|
|
&i.Entity,
|
|
&i.LibraryID,
|
|
&i.Artist,
|
|
&i.Title,
|
|
&i.Scope,
|
|
&i.Secondary,
|
|
&i.State,
|
|
&i.ParentID,
|
|
&i.Attempts,
|
|
&i.LastError,
|
|
&i.LastTriedAt,
|
|
&i.NextTryAt,
|
|
&i.ExternalIds,
|
|
&i.CreatedAt,
|
|
&i.UpdatedAt,
|
|
); err != nil {
|
|
return nil, err
|
|
}
|
|
items = append(items, i)
|
|
}
|
|
if err := rows.Close(); err != nil {
|
|
return nil, err
|
|
}
|
|
if err := rows.Err(); err != nil {
|
|
return nil, err
|
|
}
|
|
return items, nil
|
|
}
|
|
|
|
const listDownloadItemsForDownload = `-- 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
|
|
`
|
|
|
|
func (q *Queries) ListDownloadItemsForDownload(ctx context.Context, downloadID string) ([]DownloadItem, error) {
|
|
rows, err := q.db.QueryContext(ctx, listDownloadItemsForDownload, downloadID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer rows.Close()
|
|
var items []DownloadItem
|
|
for rows.Next() {
|
|
var i DownloadItem
|
|
if err := rows.Scan(
|
|
&i.ID,
|
|
&i.DownloadID,
|
|
&i.ProviderID,
|
|
&i.TransportID,
|
|
&i.ExternalID,
|
|
&i.Candidate,
|
|
&i.State,
|
|
&i.StagingDir,
|
|
&i.BytesDone,
|
|
&i.BytesTotal,
|
|
&i.ImportedPaths,
|
|
&i.Error,
|
|
&i.CreatedAt,
|
|
&i.UpdatedAt,
|
|
); err != nil {
|
|
return nil, err
|
|
}
|
|
items = append(items, i)
|
|
}
|
|
if err := rows.Close(); err != nil {
|
|
return nil, err
|
|
}
|
|
if err := rows.Err(); err != nil {
|
|
return nil, err
|
|
}
|
|
return items, nil
|
|
}
|
|
|
|
const listDownloadProviders = `-- name: ListDownloadProviders :many
|
|
SELECT id, kind, name, enabled, priority, settings, created_at
|
|
FROM download_providers
|
|
ORDER BY priority DESC, name
|
|
`
|
|
|
|
func (q *Queries) ListDownloadProviders(ctx context.Context) ([]DownloadProvider, error) {
|
|
rows, err := q.db.QueryContext(ctx, listDownloadProviders)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer rows.Close()
|
|
var items []DownloadProvider
|
|
for rows.Next() {
|
|
var i DownloadProvider
|
|
if err := rows.Scan(
|
|
&i.ID,
|
|
&i.Kind,
|
|
&i.Name,
|
|
&i.Enabled,
|
|
&i.Priority,
|
|
&i.Settings,
|
|
&i.CreatedAt,
|
|
); err != nil {
|
|
return nil, err
|
|
}
|
|
items = append(items, i)
|
|
}
|
|
if err := rows.Close(); err != nil {
|
|
return nil, err
|
|
}
|
|
if err := rows.Err(); err != nil {
|
|
return nil, err
|
|
}
|
|
return items, nil
|
|
}
|
|
|
|
const listDownloadRequests = `-- name: ListDownloadRequests :many
|
|
SELECT id, mbid, entity, library_id, artist, title, scope, secondary, state, parent_id, attempts, last_error, last_tried_at, next_try_at, external_ids, created_at, updated_at FROM download_requests
|
|
ORDER BY
|
|
CASE state WHEN 'wanted' THEN 0 WHEN 'paused' THEN 1 ELSE 2 END,
|
|
artist, title
|
|
`
|
|
|
|
func (q *Queries) ListDownloadRequests(ctx context.Context) ([]DownloadRequest, error) {
|
|
rows, err := q.db.QueryContext(ctx, listDownloadRequests)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer rows.Close()
|
|
var items []DownloadRequest
|
|
for rows.Next() {
|
|
var i DownloadRequest
|
|
if err := rows.Scan(
|
|
&i.ID,
|
|
&i.Mbid,
|
|
&i.Entity,
|
|
&i.LibraryID,
|
|
&i.Artist,
|
|
&i.Title,
|
|
&i.Scope,
|
|
&i.Secondary,
|
|
&i.State,
|
|
&i.ParentID,
|
|
&i.Attempts,
|
|
&i.LastError,
|
|
&i.LastTriedAt,
|
|
&i.NextTryAt,
|
|
&i.ExternalIds,
|
|
&i.CreatedAt,
|
|
&i.UpdatedAt,
|
|
); err != nil {
|
|
return nil, err
|
|
}
|
|
items = append(items, i)
|
|
}
|
|
if err := rows.Close(); err != nil {
|
|
return nil, err
|
|
}
|
|
if err := rows.Err(); err != nil {
|
|
return nil, err
|
|
}
|
|
return items, nil
|
|
}
|
|
|
|
const listDownloadRequestsByEntity = `-- name: ListDownloadRequestsByEntity :many
|
|
SELECT id, mbid, entity, library_id, artist, title, scope, secondary, state, parent_id, attempts, last_error, last_tried_at, next_try_at, external_ids, created_at, updated_at FROM download_requests
|
|
WHERE entity = ? AND state = ?
|
|
ORDER BY id
|
|
`
|
|
|
|
type ListDownloadRequestsByEntityParams struct {
|
|
Entity string
|
|
State string
|
|
}
|
|
|
|
func (q *Queries) ListDownloadRequestsByEntity(ctx context.Context, arg ListDownloadRequestsByEntityParams) ([]DownloadRequest, error) {
|
|
rows, err := q.db.QueryContext(ctx, listDownloadRequestsByEntity, arg.Entity, arg.State)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer rows.Close()
|
|
var items []DownloadRequest
|
|
for rows.Next() {
|
|
var i DownloadRequest
|
|
if err := rows.Scan(
|
|
&i.ID,
|
|
&i.Mbid,
|
|
&i.Entity,
|
|
&i.LibraryID,
|
|
&i.Artist,
|
|
&i.Title,
|
|
&i.Scope,
|
|
&i.Secondary,
|
|
&i.State,
|
|
&i.ParentID,
|
|
&i.Attempts,
|
|
&i.LastError,
|
|
&i.LastTriedAt,
|
|
&i.NextTryAt,
|
|
&i.ExternalIds,
|
|
&i.CreatedAt,
|
|
&i.UpdatedAt,
|
|
); err != nil {
|
|
return nil, err
|
|
}
|
|
items = append(items, i)
|
|
}
|
|
if err := rows.Close(); err != nil {
|
|
return nil, err
|
|
}
|
|
if err := rows.Err(); err != nil {
|
|
return nil, err
|
|
}
|
|
return items, nil
|
|
}
|
|
|
|
const listDownloads = `-- 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 ?
|
|
`
|
|
|
|
func (q *Queries) ListDownloads(ctx context.Context, limit int64) ([]DownloadDownload, error) {
|
|
rows, err := q.db.QueryContext(ctx, listDownloads, limit)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer rows.Close()
|
|
var items []DownloadDownload
|
|
for rows.Next() {
|
|
var i DownloadDownload
|
|
if err := rows.Scan(
|
|
&i.ID,
|
|
&i.LibraryID,
|
|
&i.Source,
|
|
&i.RequestID,
|
|
&i.ReleaseMbid,
|
|
&i.ReleaseGroupMbid,
|
|
&i.RecordingMbid,
|
|
&i.Artist,
|
|
&i.Album,
|
|
&i.Query,
|
|
&i.Expected,
|
|
&i.State,
|
|
&i.Error,
|
|
&i.CreatedAt,
|
|
&i.UpdatedAt,
|
|
); err != nil {
|
|
return nil, err
|
|
}
|
|
items = append(items, i)
|
|
}
|
|
if err := rows.Close(); err != nil {
|
|
return nil, err
|
|
}
|
|
if err := rows.Err(); err != nil {
|
|
return nil, err
|
|
}
|
|
return items, nil
|
|
}
|
|
|
|
const listDueDownloadRequests = `-- name: ListDueDownloadRequests :many
|
|
SELECT id, mbid, entity, library_id, artist, title, scope, secondary, state, parent_id, attempts, last_error, last_tried_at, next_try_at, external_ids, created_at, updated_at 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 ?
|
|
`
|
|
|
|
// 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.
|
|
func (q *Queries) ListDueDownloadRequests(ctx context.Context, limit int64) ([]DownloadRequest, error) {
|
|
rows, err := q.db.QueryContext(ctx, listDueDownloadRequests, limit)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer rows.Close()
|
|
var items []DownloadRequest
|
|
for rows.Next() {
|
|
var i DownloadRequest
|
|
if err := rows.Scan(
|
|
&i.ID,
|
|
&i.Mbid,
|
|
&i.Entity,
|
|
&i.LibraryID,
|
|
&i.Artist,
|
|
&i.Title,
|
|
&i.Scope,
|
|
&i.Secondary,
|
|
&i.State,
|
|
&i.ParentID,
|
|
&i.Attempts,
|
|
&i.LastError,
|
|
&i.LastTriedAt,
|
|
&i.NextTryAt,
|
|
&i.ExternalIds,
|
|
&i.CreatedAt,
|
|
&i.UpdatedAt,
|
|
); err != nil {
|
|
return nil, err
|
|
}
|
|
items = append(items, i)
|
|
}
|
|
if err := rows.Close(); err != nil {
|
|
return nil, err
|
|
}
|
|
if err := rows.Err(); err != nil {
|
|
return nil, err
|
|
}
|
|
return items, nil
|
|
}
|
|
|
|
const listLiveDownloadItems = `-- 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
|
|
`
|
|
|
|
func (q *Queries) ListLiveDownloadItems(ctx context.Context) ([]DownloadItem, error) {
|
|
rows, err := q.db.QueryContext(ctx, listLiveDownloadItems)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer rows.Close()
|
|
var items []DownloadItem
|
|
for rows.Next() {
|
|
var i DownloadItem
|
|
if err := rows.Scan(
|
|
&i.ID,
|
|
&i.DownloadID,
|
|
&i.ProviderID,
|
|
&i.TransportID,
|
|
&i.ExternalID,
|
|
&i.Candidate,
|
|
&i.State,
|
|
&i.StagingDir,
|
|
&i.BytesDone,
|
|
&i.BytesTotal,
|
|
&i.ImportedPaths,
|
|
&i.Error,
|
|
&i.CreatedAt,
|
|
&i.UpdatedAt,
|
|
); err != nil {
|
|
return nil, err
|
|
}
|
|
items = append(items, i)
|
|
}
|
|
if err := rows.Close(); err != nil {
|
|
return nil, err
|
|
}
|
|
if err := rows.Err(); err != nil {
|
|
return nil, err
|
|
}
|
|
return items, nil
|
|
}
|
|
|
|
const listLiveDownloads = `-- 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
|
|
`
|
|
|
|
func (q *Queries) ListLiveDownloads(ctx context.Context) ([]DownloadDownload, error) {
|
|
rows, err := q.db.QueryContext(ctx, listLiveDownloads)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer rows.Close()
|
|
var items []DownloadDownload
|
|
for rows.Next() {
|
|
var i DownloadDownload
|
|
if err := rows.Scan(
|
|
&i.ID,
|
|
&i.LibraryID,
|
|
&i.Source,
|
|
&i.RequestID,
|
|
&i.ReleaseMbid,
|
|
&i.ReleaseGroupMbid,
|
|
&i.RecordingMbid,
|
|
&i.Artist,
|
|
&i.Album,
|
|
&i.Query,
|
|
&i.Expected,
|
|
&i.State,
|
|
&i.Error,
|
|
&i.CreatedAt,
|
|
&i.UpdatedAt,
|
|
); err != nil {
|
|
return nil, err
|
|
}
|
|
items = append(items, i)
|
|
}
|
|
if err := rows.Close(); err != nil {
|
|
return nil, err
|
|
}
|
|
if err := rows.Err(); err != nil {
|
|
return nil, err
|
|
}
|
|
return items, nil
|
|
}
|
|
|
|
const listWantedDownloadRequests = `-- name: ListWantedDownloadRequests :many
|
|
SELECT id, mbid, entity, library_id, artist, title, scope, secondary, state, parent_id, attempts, last_error, last_tried_at, next_try_at, external_ids, created_at, updated_at FROM download_requests
|
|
WHERE state = 'wanted'
|
|
AND entity <> 'artist'
|
|
ORDER BY attempts, created_at
|
|
LIMIT ?
|
|
`
|
|
|
|
// 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.
|
|
func (q *Queries) ListWantedDownloadRequests(ctx context.Context, limit int64) ([]DownloadRequest, error) {
|
|
rows, err := q.db.QueryContext(ctx, listWantedDownloadRequests, limit)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer rows.Close()
|
|
var items []DownloadRequest
|
|
for rows.Next() {
|
|
var i DownloadRequest
|
|
if err := rows.Scan(
|
|
&i.ID,
|
|
&i.Mbid,
|
|
&i.Entity,
|
|
&i.LibraryID,
|
|
&i.Artist,
|
|
&i.Title,
|
|
&i.Scope,
|
|
&i.Secondary,
|
|
&i.State,
|
|
&i.ParentID,
|
|
&i.Attempts,
|
|
&i.LastError,
|
|
&i.LastTriedAt,
|
|
&i.NextTryAt,
|
|
&i.ExternalIds,
|
|
&i.CreatedAt,
|
|
&i.UpdatedAt,
|
|
); err != nil {
|
|
return nil, err
|
|
}
|
|
items = append(items, i)
|
|
}
|
|
if err := rows.Close(); err != nil {
|
|
return nil, err
|
|
}
|
|
if err := rows.Err(); err != nil {
|
|
return nil, err
|
|
}
|
|
return items, nil
|
|
}
|
|
|
|
const recordDownloadRequestAttempt = `-- 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 = ?
|
|
`
|
|
|
|
type RecordDownloadRequestAttemptParams struct {
|
|
LastError string
|
|
NextTryAt sql.NullTime
|
|
ID int64
|
|
}
|
|
|
|
func (q *Queries) RecordDownloadRequestAttempt(ctx context.Context, arg RecordDownloadRequestAttemptParams) error {
|
|
_, err := q.db.ExecContext(ctx, recordDownloadRequestAttempt, arg.LastError, arg.NextTryAt, arg.ID)
|
|
return err
|
|
}
|
|
|
|
const satisfyDownloadRequest = `-- name: SatisfyDownloadRequest :exec
|
|
UPDATE download_requests
|
|
SET state = 'satisfied', last_error = '', next_try_at = NULL,
|
|
updated_at = CURRENT_TIMESTAMP
|
|
WHERE id = ?
|
|
`
|
|
|
|
func (q *Queries) SatisfyDownloadRequest(ctx context.Context, id int64) error {
|
|
_, err := q.db.ExecContext(ctx, satisfyDownloadRequest, id)
|
|
return err
|
|
}
|
|
|
|
const setDownloadItemExternalID = `-- name: SetDownloadItemExternalID :exec
|
|
UPDATE download_items
|
|
SET external_id = ?, updated_at = CURRENT_TIMESTAMP
|
|
WHERE id = ?
|
|
`
|
|
|
|
type SetDownloadItemExternalIDParams struct {
|
|
ExternalID string
|
|
ID string
|
|
}
|
|
|
|
func (q *Queries) SetDownloadItemExternalID(ctx context.Context, arg SetDownloadItemExternalIDParams) error {
|
|
_, err := q.db.ExecContext(ctx, setDownloadItemExternalID, arg.ExternalID, arg.ID)
|
|
return err
|
|
}
|
|
|
|
const setDownloadItemImported = `-- name: SetDownloadItemImported :exec
|
|
UPDATE download_items
|
|
SET imported_paths = ?, state = 'complete', error = '',
|
|
updated_at = CURRENT_TIMESTAMP
|
|
WHERE id = ?
|
|
`
|
|
|
|
type SetDownloadItemImportedParams struct {
|
|
ImportedPaths string
|
|
ID string
|
|
}
|
|
|
|
func (q *Queries) SetDownloadItemImported(ctx context.Context, arg SetDownloadItemImportedParams) error {
|
|
_, err := q.db.ExecContext(ctx, setDownloadItemImported, arg.ImportedPaths, arg.ID)
|
|
return err
|
|
}
|
|
|
|
const setDownloadItemProgress = `-- name: SetDownloadItemProgress :exec
|
|
UPDATE download_items
|
|
SET bytes_done = ?, bytes_total = ?, updated_at = CURRENT_TIMESTAMP
|
|
WHERE id = ?
|
|
`
|
|
|
|
type SetDownloadItemProgressParams struct {
|
|
BytesDone int64
|
|
BytesTotal int64
|
|
ID string
|
|
}
|
|
|
|
func (q *Queries) SetDownloadItemProgress(ctx context.Context, arg SetDownloadItemProgressParams) error {
|
|
_, err := q.db.ExecContext(ctx, setDownloadItemProgress, arg.BytesDone, arg.BytesTotal, arg.ID)
|
|
return err
|
|
}
|
|
|
|
const setDownloadItemState = `-- name: SetDownloadItemState :exec
|
|
UPDATE download_items
|
|
SET state = ?, error = ?, updated_at = CURRENT_TIMESTAMP
|
|
WHERE id = ?
|
|
`
|
|
|
|
type SetDownloadItemStateParams struct {
|
|
State string
|
|
Error string
|
|
ID string
|
|
}
|
|
|
|
func (q *Queries) SetDownloadItemState(ctx context.Context, arg SetDownloadItemStateParams) error {
|
|
_, err := q.db.ExecContext(ctx, setDownloadItemState, arg.State, arg.Error, arg.ID)
|
|
return err
|
|
}
|
|
|
|
const setDownloadRequestExternalIDs = `-- name: SetDownloadRequestExternalIDs :exec
|
|
UPDATE download_requests
|
|
SET external_ids = ?, updated_at = CURRENT_TIMESTAMP
|
|
WHERE id = ?
|
|
`
|
|
|
|
type SetDownloadRequestExternalIDsParams struct {
|
|
ExternalIds string
|
|
ID int64
|
|
}
|
|
|
|
func (q *Queries) SetDownloadRequestExternalIDs(ctx context.Context, arg SetDownloadRequestExternalIDsParams) error {
|
|
_, err := q.db.ExecContext(ctx, setDownloadRequestExternalIDs, arg.ExternalIds, arg.ID)
|
|
return err
|
|
}
|
|
|
|
const setDownloadRequestState = `-- name: SetDownloadRequestState :exec
|
|
UPDATE download_requests
|
|
SET state = ?, last_error = ?, updated_at = CURRENT_TIMESTAMP
|
|
WHERE id = ?
|
|
`
|
|
|
|
type SetDownloadRequestStateParams struct {
|
|
State string
|
|
LastError string
|
|
ID int64
|
|
}
|
|
|
|
func (q *Queries) SetDownloadRequestState(ctx context.Context, arg SetDownloadRequestStateParams) error {
|
|
_, err := q.db.ExecContext(ctx, setDownloadRequestState, arg.State, arg.LastError, arg.ID)
|
|
return err
|
|
}
|
|
|
|
const setDownloadState = `-- name: SetDownloadState :exec
|
|
UPDATE download_downloads
|
|
SET state = ?, error = ?, updated_at = CURRENT_TIMESTAMP
|
|
WHERE id = ?
|
|
`
|
|
|
|
type SetDownloadStateParams struct {
|
|
State string
|
|
Error string
|
|
ID string
|
|
}
|
|
|
|
func (q *Queries) SetDownloadState(ctx context.Context, arg SetDownloadStateParams) error {
|
|
_, err := q.db.ExecContext(ctx, setDownloadState, arg.State, arg.Error, arg.ID)
|
|
return err
|
|
}
|
|
|
|
const updateDownloadProvider = `-- name: UpdateDownloadProvider :exec
|
|
UPDATE download_providers
|
|
SET name = ?, enabled = ?, priority = ?, settings = ?
|
|
WHERE id = ?
|
|
`
|
|
|
|
type UpdateDownloadProviderParams struct {
|
|
Name string
|
|
Enabled int64
|
|
Priority int64
|
|
Settings string
|
|
ID int64
|
|
}
|
|
|
|
func (q *Queries) UpdateDownloadProvider(ctx context.Context, arg UpdateDownloadProviderParams) error {
|
|
_, err := q.db.ExecContext(ctx, updateDownloadProvider,
|
|
arg.Name,
|
|
arg.Enabled,
|
|
arg.Priority,
|
|
arg.Settings,
|
|
arg.ID,
|
|
)
|
|
return err
|
|
}
|
|
|
|
const upsertDownloadRequest = `-- name: UpsertDownloadRequest :one
|
|
|
|
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
|
|
`
|
|
|
|
type UpsertDownloadRequestParams struct {
|
|
Mbid string
|
|
Entity string
|
|
LibraryID int64
|
|
Artist string
|
|
Title string
|
|
Scope string
|
|
Secondary int64
|
|
ParentID sql.NullInt64
|
|
}
|
|
|
|
// ---------------------------------------------------------------------
|
|
// Requests (durable "I asked for this" records)
|
|
// ---------------------------------------------------------------------
|
|
// 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.
|
|
func (q *Queries) UpsertDownloadRequest(ctx context.Context, arg UpsertDownloadRequestParams) (int64, error) {
|
|
row := q.db.QueryRowContext(ctx, upsertDownloadRequest,
|
|
arg.Mbid,
|
|
arg.Entity,
|
|
arg.LibraryID,
|
|
arg.Artist,
|
|
arg.Title,
|
|
arg.Scope,
|
|
arg.Secondary,
|
|
arg.ParentID,
|
|
)
|
|
var id int64
|
|
err := row.Scan(&id)
|
|
return id, err
|
|
}
|