diff --git a/internal/database/download_repository.go b/internal/database/download_repository.go index 535d982..0a39efb 100644 --- a/internal/database/download_repository.go +++ b/internal/database/download_repository.go @@ -16,8 +16,8 @@ type Download struct { Quality string State string QbitHash string - SavePath string - ErrorMessage string + SavePath *string + ErrorMessage *string QueuedAt time.Time StartedAt *time.Time CompletedAt *time.Time @@ -107,6 +107,19 @@ func (r *DownloadRepository) GetByAlbumID(ctx context.Context, albumID string) ( return downloads, nil } +func (r *DownloadRepository) GetActiveByTorrentID(ctx context.Context, torrentID string) (*Download, error) { + d := &Download{} + err := r.pool.QueryRow(ctx, + `SELECT id, torrent_id, album_id, format, quality, state, qbit_hash, save_path, error_message, queued_at, started_at, completed_at, created_at, updated_at + FROM downloads WHERE torrent_id = $1 AND state NOT IN ('failed') + ORDER BY created_at DESC LIMIT 1`, torrentID, + ).Scan(&d.ID, &d.TorrentID, &d.AlbumID, &d.Format, &d.Quality, &d.State, &d.QbitHash, &d.SavePath, &d.ErrorMessage, &d.QueuedAt, &d.StartedAt, &d.CompletedAt, &d.CreatedAt, &d.UpdatedAt) + if err != nil { + return nil, fmt.Errorf("getting active download by torrent: %w", err) + } + return d, nil +} + func (r *DownloadRepository) GetActive(ctx context.Context) ([]*Download, error) { rows, err := r.pool.Query(ctx, `SELECT id, torrent_id, album_id, format, quality, state, qbit_hash, save_path, error_message, queued_at, started_at, completed_at, created_at, updated_at diff --git a/internal/service.go b/internal/service.go index d1688a4..f200b8e 100644 --- a/internal/service.go +++ b/internal/service.go @@ -170,7 +170,7 @@ func (service *MusicAgregatorService) buildAlbumsForArtist(ctx context.Context, State: best.State, Format: best.Format, Quality: best.Quality, - SavePath: best.SavePath, + SavePath: derefStr(best.SavePath), } } } else { @@ -228,7 +228,7 @@ func (service *MusicAgregatorService) GetAlbum(ctx context.Context, req *pb.GetA State: best.State, Format: best.Format, Quality: best.Quality, - SavePath: best.SavePath, + SavePath: derefStr(best.SavePath), } } @@ -514,14 +514,10 @@ func (service *MusicAgregatorService) saveTorrentAndDownload(ctx context.Context return } - existingDownloads, err := service.downloads.GetByAlbumID(ctx, dbAlbumID) - if err == nil { - for _, d := range existingDownloads { - if d.TorrentID == savedTorrent.ID && d.State != "failed" { - log.Info().Str("hash", best.rel.InfoHash).Str("state", d.State).Msg("active download already exists, skipping") - return - } - } + existingDownload, err := service.downloads.GetActiveByTorrentID(ctx, savedTorrent.ID) + if err == nil && existingDownload != nil { + log.Info().Str("hash", best.rel.InfoHash).Str("state", existingDownload.State).Msg("active download already exists, skipping") + return } download := &database.Download{ @@ -647,7 +643,7 @@ func (service *MusicAgregatorService) buildAlbumDetail(ctx context.Context, dbAl State: best.State, Format: best.Format, Quality: best.Quality, - SavePath: best.SavePath, + SavePath: derefStr(best.SavePath), } } @@ -667,6 +663,13 @@ func toProtoMonitorState(state database.MonitorState) pb.MonitorState { } } +func derefStr(s *string) string { + if s == nil { + return "" + } + return *s +} + func downloadTorrentData(url string) ([]byte, error) { client := &http.Client{Timeout: 30 * time.Second} resp, err := client.Get(url)