diff --git a/scanner/phase_1_folders.go b/scanner/phase_1_folders.go index b33814fdc..3d04d525d 100644 --- a/scanner/phase_1_folders.go +++ b/scanner/phase_1_folders.go @@ -26,10 +26,10 @@ import ( "github.com/navidrome/navidrome/utils/slice" ) -func createPhaseFolders(ctx context.Context, state *scanState, ds model.DataStore, cw artwork.CacheWarmer, libs []model.Library) *phaseFolders { +func createPhaseFolders(ctx context.Context, state *scanState, ds model.DataStore, cw artwork.CacheWarmer) *phaseFolders { var jobs []*scanJob var updatedLibs []model.Library - for _, lib := range libs { + for _, lib := range state.libraries { if lib.LastScanStartedAt.IsZero() { err := ds.Library(ctx).ScanBegin(lib.ID, state.fullScan) if err != nil { diff --git a/scanner/phase_3_refresh_albums.go b/scanner/phase_3_refresh_albums.go index f51aa8f4b..33e0fed01 100644 --- a/scanner/phase_3_refresh_albums.go +++ b/scanner/phase_3_refresh_albums.go @@ -27,14 +27,13 @@ import ( type phaseRefreshAlbums struct { ds model.DataStore ctx context.Context - libs model.Libraries refreshed atomic.Uint32 skipped atomic.Uint32 state *scanState } -func createPhaseRefreshAlbums(ctx context.Context, state *scanState, ds model.DataStore, libs model.Libraries) *phaseRefreshAlbums { - return &phaseRefreshAlbums{ctx: ctx, ds: ds, libs: libs, state: state} +func createPhaseRefreshAlbums(ctx context.Context, state *scanState, ds model.DataStore) *phaseRefreshAlbums { + return &phaseRefreshAlbums{ctx: ctx, ds: ds, state: state} } func (p *phaseRefreshAlbums) description() string { @@ -47,7 +46,7 @@ func (p *phaseRefreshAlbums) producer() ppl.Producer[*model.Album] { func (p *phaseRefreshAlbums) produce(put func(album *model.Album)) error { count := 0 - for _, lib := range p.libs { + for _, lib := range p.state.libraries { cursor, err := p.ds.Album(p.ctx).GetTouchedAlbums(lib.ID) if err != nil { return fmt.Errorf("loading touched albums: %w", err) diff --git a/scanner/phase_3_refresh_albums_test.go b/scanner/phase_3_refresh_albums_test.go index dea2556f0..1f0baf428 100644 --- a/scanner/phase_3_refresh_albums_test.go +++ b/scanner/phase_3_refresh_albums_test.go @@ -32,8 +32,8 @@ var _ = Describe("phaseRefreshAlbums", func() { {ID: 1, Name: "Library 1"}, {ID: 2, Name: "Library 2"}, } - state = &scanState{} - phase = createPhaseRefreshAlbums(ctx, state, ds, libs) + state = &scanState{libraries: libs} + phase = createPhaseRefreshAlbums(ctx, state, ds) }) Describe("description", func() { diff --git a/scanner/scanner.go b/scanner/scanner.go index 543b9b46a..c0bf98c26 100644 --- a/scanner/scanner.go +++ b/scanner/scanner.go @@ -39,6 +39,10 @@ func (s *scanState) sendProgress(info *ProgressInfo) { } } +func (s *scanState) isSelectiveScan() bool { + return len(s.targets) > 0 +} + func (s *scanState) sendWarning(msg string) { s.sendProgress(&ProgressInfo{Warning: msg}) } @@ -68,10 +72,7 @@ func (s *scannerImpl) scanFolders(ctx context.Context, fullScan bool, targets [] return } - var libs model.Libraries - isSelectiveScan := len(targets) > 0 - - if isSelectiveScan { + if len(targets) > 0 { // Selective scan: filter libraries and build targets map state.targets = make(map[int][]string) @@ -84,24 +85,23 @@ func (s *scannerImpl) scanFolders(ctx context.Context, fullScan bool, targets [] } // Filter libraries to only those in targets - libs = slice.Filter(allLibs, func(lib model.Library) bool { + state.libraries = slice.Filter(allLibs, func(lib model.Library) bool { return len(state.targets[lib.ID]) > 0 }) - log.Info(ctx, "Scanner: Starting selective scan", "fullScan", state.fullScan, "numLibraries", len(libs), "numTargets", len(targets)) + log.Info(ctx, "Scanner: Starting selective scan", "fullScan", state.fullScan, "numLibraries", len(state.libraries), "numTargets", len(targets)) } else { // Full library scan - libs = allLibs - log.Info(ctx, "Scanner: Starting scan", "fullScan", state.fullScan, "numLibraries", len(libs)) + state.libraries = allLibs + log.Info(ctx, "Scanner: Starting scan", "fullScan", state.fullScan, "numLibraries", len(state.libraries)) } - state.libraries = libs // Store scan type and start time scanType := "quick" if state.fullScan { scanType = "full" } - if isSelectiveScan { + if state.isSelectiveScan() { scanType += "-selective" } _ = s.ds.Property(ctx).Put(consts.LastScanTypeKey, scanType) @@ -109,11 +109,11 @@ func (s *scannerImpl) scanFolders(ctx context.Context, fullScan bool, targets [] // if there was a full scan in progress, force a full scan if !state.fullScan { - for _, lib := range libs { + for _, lib := range state.libraries { if lib.FullScanInProgress { log.Info(ctx, "Scanner: Interrupted full scan detected", "lib", lib.Name) state.fullScan = true - if isSelectiveScan { + if state.isSelectiveScan() { _ = s.ds.Property(ctx).Put(consts.LastScanTypeKey, "full-selective") } else { _ = s.ds.Property(ctx).Put(consts.LastScanTypeKey, "full") @@ -125,7 +125,7 @@ func (s *scannerImpl) scanFolders(ctx context.Context, fullScan bool, targets [] err = run.Sequentially( // Phase 1: Scan all libraries and import new/updated files - runPhase[*folderEntry](ctx, 1, createPhaseFolders(ctx, &state, s.ds, s.cw, libs)), + runPhase[*folderEntry](ctx, 1, createPhaseFolders(ctx, &state, s.ds, s.cw)), // Phase 2: Process missing files, checking for moves runPhase[*missingTracks](ctx, 2, createPhaseMissingTracks(ctx, &state, s.ds)), @@ -133,7 +133,7 @@ func (s *scannerImpl) scanFolders(ctx context.Context, fullScan bool, targets [] // Phases 3 and 4 can be run in parallel run.Parallel( // Phase 3: Refresh all new/changed albums and update artists - runPhase[*model.Album](ctx, 3, createPhaseRefreshAlbums(ctx, &state, s.ds, libs)), + runPhase[*model.Album](ctx, 3, createPhaseRefreshAlbums(ctx, &state, s.ds)), // Phase 4: Import/update playlists runPhase[*model.Folder](ctx, 4, createPhasePlaylists(ctx, &state, s.ds, s.pls, s.cw)), @@ -166,7 +166,7 @@ func (s *scannerImpl) scanFolders(ctx context.Context, fullScan bool, targets [] state.sendProgress(&ProgressInfo{ChangesDetected: true}) } - if isSelectiveScan { + if state.isSelectiveScan() { log.Info(ctx, "Scanner: Finished scanning selected folders", "duration", time.Since(startTime), "numTargets", len(targets)) } else { log.Info(ctx, "Scanner: Finished scanning all libraries", "duration", time.Since(startTime))