// Code generated by sqlc. DO NOT EDIT. // versions: // sqlc v1.31.1 // source: backups.sql package dbq import ( "context" "github.com/jackc/pgx/v5/pgtype" ) const backupMusicProgress = `-- name: BackupMusicProgress :one SELECT count(*)::bigint AS total_files, COALESCE(sum(t.file_size), 0)::bigint AS total_bytes, count(*) FILTER (WHERE m.error = '' AND m.size = t.file_size AND t.updated_at <= m.checked_at)::bigint AS sent_files, COALESCE(sum(t.file_size) FILTER (WHERE m.error = '' AND m.size = t.file_size AND t.updated_at <= m.checked_at), 0)::bigint AS sent_bytes, count(*) FILTER (WHERE m.error <> '' AND m.size = t.file_size AND t.updated_at <= m.checked_at)::bigint AS refused_files FROM tracks t LEFT JOIN backup_music_files m ON m.track_id = t.id WHERE t.missing_since IS NULL ` type BackupMusicProgressRow struct { TotalFiles int64 TotalBytes int64 SentFiles int64 SentBytes int64 RefusedFiles int64 } // How much of the library the backup holds as it is now. func (q *Queries) BackupMusicProgress(ctx context.Context) (BackupMusicProgressRow, error) { row := q.db.QueryRow(ctx, backupMusicProgress) var i BackupMusicProgressRow err := row.Scan( &i.TotalFiles, &i.TotalBytes, &i.SentFiles, &i.SentBytes, &i.RefusedFiles, ) return i, err } const backupRunTimes = `-- name: BackupRunTimes :one SELECT COALESCE((SELECT max(started_at) FROM backup_runs WHERE status = 'succeeded'), 'epoch'::timestamptz)::timestamptz AS last_success, COALESCE((SELECT max(started_at) FROM backup_runs), 'epoch'::timestamptz)::timestamptz AS last_attempt, COALESCE((SELECT min(started_at) FROM backup_runs WHERE status = 'failed' AND started_at > COALESCE((SELECT max(started_at) FROM backup_runs WHERE status = 'succeeded'), 'epoch'::timestamptz)), 'epoch'::timestamptz)::timestamptz AS failing_since ` type BackupRunTimesRow struct { LastSuccess pgtype.Timestamptz LastAttempt pgtype.Timestamptz FailingSince pgtype.Timestamptz } // The times the verdict turns on. A run that never happened is the epoch, // so the row always exists. failing_since is the first failure after the last // success, and the epoch when the latest finished run succeeded. func (q *Queries) BackupRunTimes(ctx context.Context) (BackupRunTimesRow, error) { row := q.db.QueryRow(ctx, backupRunTimes) var i BackupRunTimesRow err := row.Scan(&i.LastSuccess, &i.LastAttempt, &i.FailingSince) return i, err } const failUnfinishedBackupRuns = `-- name: FailUnfinishedBackupRuns :execrows UPDATE backup_runs SET status = 'failed', finished_at = now(), error = 'The server stopped while the backup was running.' WHERE status = 'running' ` func (q *Queries) FailUnfinishedBackupRuns(ctx context.Context) (int64, error) { result, err := q.db.Exec(ctx, failUnfinishedBackupRuns) if err != nil { return 0, err } return result.RowsAffected(), nil } const finishBackupRun = `-- name: FinishBackupRun :exec UPDATE backup_runs SET status = $2, finished_at = now(), location = $3, bytes = $4, error = $5, music_files = $6, music_bytes = $7, music_note = $8 WHERE id = $1 ` type FinishBackupRunParams struct { ID pgtype.UUID Status string Location string Bytes int64 Error string MusicFiles int32 MusicBytes int64 MusicNote string } func (q *Queries) FinishBackupRun(ctx context.Context, arg FinishBackupRunParams) error { _, err := q.db.Exec(ctx, finishBackupRun, arg.ID, arg.Status, arg.Location, arg.Bytes, arg.Error, arg.MusicFiles, arg.MusicBytes, arg.MusicNote, ) return err } const getBackupSettings = `-- name: GetBackupSettings :one SELECT id, enabled, destination, folder, endpoint, bucket, access_key, secret_key, run_hour, upload_limit_kib, updated_at, include_music FROM backup_settings WHERE id = true ` // Minstrel's own backup: its settings and its runs. func (q *Queries) GetBackupSettings(ctx context.Context) (BackupSetting, error) { row := q.db.QueryRow(ctx, getBackupSettings) var i BackupSetting err := row.Scan( &i.ID, &i.Enabled, &i.Destination, &i.Folder, &i.Endpoint, &i.Bucket, &i.AccessKey, &i.SecretKey, &i.RunHour, &i.UploadLimitKib, &i.UpdatedAt, &i.IncludeMusic, ) return i, err } const listBackupRuns = `-- name: ListBackupRuns :many SELECT id, trigger, status, started_at, finished_at, location, bytes, error, music_files, music_bytes, music_note FROM backup_runs ORDER BY started_at DESC LIMIT $1 ` func (q *Queries) ListBackupRuns(ctx context.Context, limit int32) ([]BackupRun, error) { rows, err := q.db.Query(ctx, listBackupRuns, limit) if err != nil { return nil, err } defer rows.Close() var items []BackupRun for rows.Next() { var i BackupRun if err := rows.Scan( &i.ID, &i.Trigger, &i.Status, &i.StartedAt, &i.FinishedAt, &i.Location, &i.Bytes, &i.Error, &i.MusicFiles, &i.MusicBytes, &i.MusicNote, ); err != nil { return nil, err } items = append(items, i) } if err := rows.Err(); err != nil { return nil, err } return items, nil } const pendingBackupMusic = `-- name: PendingBackupMusic :many SELECT t.id, t.file_path, t.file_size, m.size AS sent_size, m.mtime AS sent_mtime, m.error AS sent_error FROM tracks t LEFT JOIN backup_music_files m ON m.track_id = t.id WHERE t.missing_since IS NULL AND t.file_path > $1::text AND (m.track_id IS NULL OR m.size <> t.file_size OR t.updated_at > m.checked_at OR (m.error <> '' AND m.checked_at < (SELECT updated_at FROM backup_settings))) ORDER BY t.file_path LIMIT $2 ` type PendingBackupMusicParams struct { AfterPath string MaxRows int32 } type PendingBackupMusicRow struct { ID pgtype.UUID FilePath string FileSize int64 SentSize *int64 SentMtime pgtype.Timestamptz SentError *string } // Library files the backup may not hold as they are now, in path order from // after_path, so a night that runs out of time carries on where it stopped: // never sent, a different size, touched by a scan since they were last // checked, or refused before the settings were last saved (a fixed key gets // another go). The caller compares the file's own size and mtime before // sending. func (q *Queries) PendingBackupMusic(ctx context.Context, arg PendingBackupMusicParams) ([]PendingBackupMusicRow, error) { rows, err := q.db.Query(ctx, pendingBackupMusic, arg.AfterPath, arg.MaxRows) if err != nil { return nil, err } defer rows.Close() var items []PendingBackupMusicRow for rows.Next() { var i PendingBackupMusicRow if err := rows.Scan( &i.ID, &i.FilePath, &i.FileSize, &i.SentSize, &i.SentMtime, &i.SentError, ); err != nil { return nil, err } items = append(items, i) } if err := rows.Err(); err != nil { return nil, err } return items, nil } const pruneBackupRuns = `-- name: PruneBackupRuns :execrows DELETE FROM backup_runs WHERE status <> 'running' AND started_at < $1 ` func (q *Queries) PruneBackupRuns(ctx context.Context, startedAt pgtype.Timestamptz) (int64, error) { result, err := q.db.Exec(ctx, pruneBackupRuns, startedAt) if err != nil { return 0, err } return result.RowsAffected(), nil } const recordBackupMusic = `-- name: RecordBackupMusic :exec INSERT INTO backup_music_files (track_id, size, mtime, location, error) VALUES ($1, $2, $3, $4, $5) ON CONFLICT (track_id) DO UPDATE SET size = EXCLUDED.size, mtime = EXCLUDED.mtime, location = EXCLUDED.location, error = EXCLUDED.error, checked_at = now() ` type RecordBackupMusicParams struct { TrackID pgtype.UUID Size int64 Mtime pgtype.Timestamptz Location string Error string } func (q *Queries) RecordBackupMusic(ctx context.Context, arg RecordBackupMusicParams) error { _, err := q.db.Exec(ctx, recordBackupMusic, arg.TrackID, arg.Size, arg.Mtime, arg.Location, arg.Error, ) return err } const refusedBackupMusic = `-- name: RefusedBackupMusic :many SELECT t.file_path, m.error, m.checked_at FROM backup_music_files m JOIN tracks t ON t.id = m.track_id WHERE m.error <> '' AND m.size = t.file_size AND t.updated_at <= m.checked_at ORDER BY m.checked_at DESC LIMIT $1 ` type RefusedBackupMusicRow struct { FilePath string Error string CheckedAt pgtype.Timestamptz } func (q *Queries) RefusedBackupMusic(ctx context.Context, limit int32) ([]RefusedBackupMusicRow, error) { rows, err := q.db.Query(ctx, refusedBackupMusic, limit) if err != nil { return nil, err } defer rows.Close() var items []RefusedBackupMusicRow for rows.Next() { var i RefusedBackupMusicRow if err := rows.Scan(&i.FilePath, &i.Error, &i.CheckedAt); err != nil { return nil, err } items = append(items, i) } if err := rows.Err(); err != nil { return nil, err } return items, nil } const saveBackupSettings = `-- name: SaveBackupSettings :exec UPDATE backup_settings SET enabled = $1, destination = $2, folder = $3, endpoint = $4, bucket = $5, access_key = $6, secret_key = $7, run_hour = $8, upload_limit_kib = $9, include_music = $10, updated_at = now() WHERE id = true ` type SaveBackupSettingsParams struct { Enabled bool Destination string Folder string Endpoint string Bucket string AccessKey string SecretKey string RunHour int16 UploadLimitKib int32 IncludeMusic bool } func (q *Queries) SaveBackupSettings(ctx context.Context, arg SaveBackupSettingsParams) error { _, err := q.db.Exec(ctx, saveBackupSettings, arg.Enabled, arg.Destination, arg.Folder, arg.Endpoint, arg.Bucket, arg.AccessKey, arg.SecretKey, arg.RunHour, arg.UploadLimitKib, arg.IncludeMusic, ) return err } const startBackupRun = `-- name: StartBackupRun :one INSERT INTO backup_runs (trigger) VALUES ($1) RETURNING id, started_at ` type StartBackupRunRow struct { ID pgtype.UUID StartedAt pgtype.Timestamptz } func (q *Queries) StartBackupRun(ctx context.Context, trigger string) (StartBackupRunRow, error) { row := q.db.QueryRow(ctx, startBackupRun, trigger) var i StartBackupRunRow err := row.Scan(&i.ID, &i.StartedAt) return i, err }