feat: add DB-backed scanner entrypoint and compute-only main hook
Implements ScanArtist/ScanAll in internal/scanner loading local/external releases via the database layer with ctx-cancellation checks, plus a compute-only run() hook that logs missing-release counts. Add table-driven tests using in-memory SQLite fixtures.
This commit is contained in:
66
internal/scanner/scan.go
Normal file
66
internal/scanner/scan.go
Normal file
@@ -0,0 +1,66 @@
|
||||
package scanner
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"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, resolveThreshold(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
|
||||
}
|
||||
|
||||
resolved := resolveThreshold(threshold)
|
||||
|
||||
var all []MissingRelease
|
||||
for _, s := range settings {
|
||||
if err := ctx.Err(); err != nil {
|
||||
return all, err
|
||||
}
|
||||
if !s.Monitored {
|
||||
continue
|
||||
}
|
||||
missing, err := ScanArtist(ctx, db, s.ID, resolved)
|
||||
if err != nil {
|
||||
return all, err
|
||||
}
|
||||
all = append(all, missing...)
|
||||
}
|
||||
|
||||
return all, nil
|
||||
}
|
||||
Reference in New Issue
Block a user