feat: add download tracking endpoints (sections 4.1, 4.2, 4.3, 4.4)

This commit is contained in:
Alexander
2026-04-29 13:44:01 +02:00
parent c307c68d88
commit 3ecc6aee62
6 changed files with 999 additions and 0 deletions
+152
View File
@@ -607,3 +607,155 @@ func (db *DB) GetArtistIDByAlbum(ctx context.Context, albumID uuid.UUID) (*uuid.
}
return &artistID, nil
}
type DownloadQueueRow struct {
ID uuid.UUID `json:"id"`
ArtistID *uuid.UUID `json:"artist_id"`
AlbumID *uuid.UUID `json:"album_id"`
DownloadID *string `json:"download_id"`
Title string `json:"title"`
Size int64 `json:"size"`
SizeLeft int64 `json:"size_left"`
Status string `json:"status"`
Progress float32 `json:"progress"`
ErrorMessage *string `json:"error_message"`
Protocol string `json:"protocol"`
Indexer *string `json:"indexer"`
DownloadClient *string `json:"download_client"`
TorrentHash *string `json:"torrent_hash"`
OutputPath *string `json:"output_path"`
AddedAt time.Time `json:"added_at"`
CompletedAt *time.Time `json:"completed_at"`
}
func (db *DB) AddToDownloadQueue(ctx context.Context, title string, size int64, torrentHash, indexer *string, albumID, artistID *uuid.UUID) (uuid.UUID, error) {
var id uuid.UUID
err := db.pool.QueryRow(ctx, `
INSERT INTO download_queue (title, size, torrent_hash, indexer, album_id, artist_id, status)
VALUES ($1, $2, $3, $4, $5, $6, 'queued')
RETURNING id
`, title, size, torrentHash, indexer, albumID, artistID).Scan(&id)
return id, err
}
func (db *DB) GetDownloadQueueItem(ctx context.Context, id uuid.UUID) (*DownloadQueueRow, error) {
var row DownloadQueueRow
err := db.pool.QueryRow(ctx, `
SELECT id, artist_id, album_id, download_id, title, size, size_left, status, progress,
error_message, protocol, indexer, download_client, torrent_hash, output_path, added_at, completed_at
FROM download_queue WHERE id = $1
`, id).Scan(&row.ID, &row.ArtistID, &row.AlbumID, &row.DownloadID, &row.Title, &row.Size,
&row.SizeLeft, &row.Status, &row.Progress, &row.ErrorMessage, &row.Protocol, &row.Indexer,
&row.DownloadClient, &row.TorrentHash, &row.OutputPath, &row.AddedAt, &row.CompletedAt)
if err != nil {
return nil, err
}
return &row, nil
}
func (db *DB) ListDownloadQueue(ctx context.Context, status *string) ([]DownloadQueueRow, error) {
var rows []DownloadQueueRow
var query string
var args []any
if status != nil {
query = `
SELECT id, artist_id, album_id, download_id, title, size, size_left, status, progress,
error_message, protocol, indexer, download_client, torrent_hash, output_path, added_at, completed_at
FROM download_queue WHERE status = $1 ORDER BY added_at DESC
`
args = []any{*status}
} else {
query = `
SELECT id, artist_id, album_id, download_id, title, size, size_left, status, progress,
error_message, protocol, indexer, download_client, torrent_hash, output_path, added_at, completed_at
FROM download_queue ORDER BY added_at DESC
`
}
dbRows, err := db.pool.Query(ctx, query, args...)
if err != nil {
return nil, err
}
defer dbRows.Close()
for dbRows.Next() {
var row DownloadQueueRow
err := dbRows.Scan(&row.ID, &row.ArtistID, &row.AlbumID, &row.DownloadID, &row.Title, &row.Size,
&row.SizeLeft, &row.Status, &row.Progress, &row.ErrorMessage, &row.Protocol, &row.Indexer,
&row.DownloadClient, &row.TorrentHash, &row.OutputPath, &row.AddedAt, &row.CompletedAt)
if err != nil {
return nil, err
}
rows = append(rows, row)
}
return rows, nil
}
func (db *DB) UpdateDownloadQueueStatus(ctx context.Context, id uuid.UUID, status string, errorMessage *string) error {
if status == "completed" {
_, err := db.pool.Exec(ctx, `
UPDATE download_queue SET status = $1, completed_at = NOW() WHERE id = $2
`, status, id)
return err
}
if errorMessage != nil {
_, err := db.pool.Exec(ctx, `
UPDATE download_queue SET status = $1, error_message = $2 WHERE id = $3
`, status, *errorMessage, id)
return err
}
_, err := db.pool.Exec(ctx, `
UPDATE download_queue SET status = $1 WHERE id = $2
`, status, id)
return err
}
func (db *DB) UpdateDownloadQueueProgress(ctx context.Context, id uuid.UUID, progress float32, sizeLeft int64, status string) error {
_, err := db.pool.Exec(ctx, `
UPDATE download_queue SET progress = $1, size_left = $2, status = $3 WHERE id = $4
`, progress, sizeLeft, status, id)
return err
}
func (db *DB) DeleteDownloadQueueItem(ctx context.Context, id uuid.UUID) error {
_, err := db.pool.Exec(ctx, `DELETE FROM download_queue WHERE id = $1`, id)
return err
}
func (db *DB) GetDownloadQueueByTorrentHash(ctx context.Context, hash string) (*DownloadQueueRow, error) {
var row DownloadQueueRow
err := db.pool.QueryRow(ctx, `
SELECT id, artist_id, album_id, download_id, title, size, size_left, status, progress,
error_message, protocol, indexer, download_client, torrent_hash, output_path, added_at, completed_at
FROM download_queue WHERE torrent_hash = $1
`, hash).Scan(&row.ID, &row.ArtistID, &row.AlbumID, &row.DownloadID, &row.Title, &row.Size,
&row.SizeLeft, &row.Status, &row.Progress, &row.ErrorMessage, &row.Protocol, &row.Indexer,
&row.DownloadClient, &row.TorrentHash, &row.OutputPath, &row.AddedAt, &row.CompletedAt)
if err != nil {
return nil, err
}
return &row, nil
}
type DownloadQueueStats struct {
Total int64 `json:"total"`
Downloading int64 `json:"downloading"`
Queued int64 `json:"queued"`
Completed int64 `json:"completed"`
Failed int64 `json:"failed"`
}
func (db *DB) GetDownloadQueueStats(ctx context.Context) (*DownloadQueueStats, error) {
var stats DownloadQueueStats
err := db.pool.QueryRow(ctx, `
SELECT
COUNT(*) as total,
COUNT(*) FILTER (WHERE status = 'downloading') as downloading,
COUNT(*) FILTER (WHERE status = 'queued') as queued,
COUNT(*) FILTER (WHERE status = 'completed') as completed,
COUNT(*) FILTER (WHERE status = 'failed') as failed
FROM download_queue
`).Scan(&stats.Total, &stats.Downloading, &stats.Queued, &stats.Completed, &stats.Failed)
return &stats, err
}