75 lines
2.2 KiB
Go
75 lines
2.2 KiB
Go
package scanner
|
|
|
|
import (
|
|
"context"
|
|
"log"
|
|
|
|
"naviwatcher/internal/database"
|
|
)
|
|
|
|
// ScanArtist loads the local albums and external releases for a single artist
|
|
// from the database and computes the list of missing releases.
|
|
//
|
|
// threshold is the fuzzy-similarity cutoff; pass 0 to use DefaultThreshold.
|
|
// The context is checked before querying the database; if it is already
|
|
// cancelled, no work is performed and the sentinel error ctx.Err() is returned.
|
|
func ScanArtist(ctx context.Context, db *database.DB, artistID string, threshold float64) ([]MissingRelease, error) {
|
|
if err := ctx.Err(); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
local, err := database.GetLocalAlbumsByArtist(db, artistID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
external, err := database.GetExternalReleasesByArtist(db, artistID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
missing := FindMissingReleases(local, external, threshold)
|
|
return missing, nil
|
|
}
|
|
|
|
// ScanAll iterates over all monitored artists (those with Monitored == true)
|
|
// and computes the missing releases for each. Results are concatenated into a
|
|
// single slice across all artists.
|
|
//
|
|
// ctx.Err() is checked between artists; if cancellation occurs mid-iteration,
|
|
// scanning stops early and the accumulated results so far are returned along
|
|
// with the cancellation error. threshold follows the same contract as
|
|
// ScanArtist (0 → DefaultThreshold).
|
|
func ScanAll(ctx context.Context, db *database.DB, threshold float64) ([]MissingRelease, error) {
|
|
settings, err := database.GetAllArtistSettings(db)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
var all []MissingRelease
|
|
var failedArtists []string
|
|
for _, s := range settings {
|
|
if err := ctx.Err(); err != nil {
|
|
return all, err
|
|
}
|
|
if !s.Monitored {
|
|
continue
|
|
}
|
|
// A transient error for one artist must not abort the whole scan and
|
|
// take down the daemon; log it and continue with the remaining artists.
|
|
missing, err := ScanArtist(ctx, db, s.ID, threshold)
|
|
if err != nil {
|
|
log.Printf("scan artist %s failed: %v", s.ID, err)
|
|
failedArtists = append(failedArtists, s.ID)
|
|
continue
|
|
}
|
|
all = append(all, missing...)
|
|
}
|
|
|
|
if n := len(failedArtists); n > 0 {
|
|
log.Printf("scan completed with %d artist(s) skipped due to errors: %v", n, failedArtists)
|
|
}
|
|
|
|
return all, nil
|
|
}
|