diff --git a/core/library.go b/core/library.go index 7abd35c8f..8e17445ec 100644 --- a/core/library.go +++ b/core/library.go @@ -21,7 +21,7 @@ import ( "github.com/navidrome/navidrome/utils/slice" ) -// Scanner interface for triggering scans +// Scanner interface for triggering scans. This is a subset of the full scanner.Scanner interface. type Scanner interface { ScanAll(ctx context.Context, fullScan bool) (warnings []string, err error) } diff --git a/scanner/controller.go b/scanner/controller.go index e34246c4b..70e2d6a69 100644 --- a/scanner/controller.go +++ b/scanner/controller.go @@ -137,11 +137,7 @@ func CallScan(ctx context.Context, ds model.DataStore, pls core.Playlists, fullS go func() { defer close(progress) scanner := &scannerImpl{ds: ds, cw: artwork.NoopCacheWarmer(), pls: pls} - if len(targets) == 0 { - scanner.scanAll(ctx, fullScan, progress) - } else { - scanner.scanFolders(ctx, fullScan, targets, progress) - } + scanner.scanFolders(ctx, fullScan, targets, progress) }() return progress, nil } @@ -161,8 +157,10 @@ type ProgressInfo struct { ForceUpdate bool } +// scanner defines the interface for different scanner implementations. +// This allows for swapping between in-process and external scanners. type scanner interface { - scanAll(ctx context.Context, fullScan bool, progress chan<- *ProgressInfo) + // scanFolders performs the actual scanning of folders. If targets is nil, it scans all libraries. scanFolders(ctx context.Context, fullScan bool, targets []ScanTarget, progress chan<- *ProgressInfo) } @@ -291,11 +289,7 @@ func (s *controller) ScanFolders(requestCtx context.Context, fullScan bool, targ go func() { defer close(progress) scanner := s.getScanner() - if len(targets) == 0 { - scanner.scanAll(ctx, fullScan, progress) - } else { - scanner.scanFolders(ctx, fullScan, targets, progress) - } + scanner.scanFolders(ctx, fullScan, targets, progress) }() // Wait for the scan to finish, sending progress events to all connected clients diff --git a/scanner/external.go b/scanner/external.go index 690748d8e..155fdf58b 100644 --- a/scanner/external.go +++ b/scanner/external.go @@ -24,10 +24,6 @@ import ( // process will forward them to the caller. type scannerExternal struct{} -func (s *scannerExternal) scanAll(ctx context.Context, fullScan bool, progress chan<- *ProgressInfo) { - s.scan(ctx, fullScan, nil, progress) -} - func (s *scannerExternal) scanFolders(ctx context.Context, fullScan bool, targets []ScanTarget, progress chan<- *ProgressInfo) { s.scan(ctx, fullScan, targets, progress) } diff --git a/scanner/scanner.go b/scanner/scanner.go index be11ec5a3..f1b42a911 100644 --- a/scanner/scanner.go +++ b/scanner/scanner.go @@ -47,10 +47,6 @@ func (s *scanState) sendError(err error) { s.sendProgress(&ProgressInfo{Error: err.Error()}) } -func (s *scannerImpl) scanAll(ctx context.Context, fullScan bool, progress chan<- *ProgressInfo) { - s.scanFolders(ctx, fullScan, nil, progress) -} - func (s *scannerImpl) scanFolders(ctx context.Context, fullScan bool, targets []ScanTarget, progress chan<- *ProgressInfo) { startTime := time.Now() diff --git a/scanner/watcher_test.go b/scanner/watcher_test.go index 6f10d9010..be813a10b 100644 --- a/scanner/watcher_test.go +++ b/scanner/watcher_test.go @@ -18,7 +18,7 @@ import ( var _ = Describe("Watcher", func() { var ctx context.Context var cancel context.CancelFunc - var mockScanner *MockScanner + var mockScanner *mockScanner var mockDS *tests.MockDataStore var w *watcher var lib *model.Library @@ -337,8 +337,8 @@ var _ = Describe("resolveFolderPath", func() { }) }) -// MockScanner implements scanner.Scanner for testing -type MockScanner struct { +// mockScanner implements scanner.Scanner for testing +type mockScanner struct { mu sync.Mutex scanAllCalls []ScanAllCall scanFoldersCalls []ScanFoldersCall @@ -354,14 +354,14 @@ type ScanFoldersCall struct { Targets []ScanTarget } -func NewMockScanner() *MockScanner { - return &MockScanner{ +func NewMockScanner() *mockScanner { + return &mockScanner{ scanAllCalls: make([]ScanAllCall, 0), scanFoldersCalls: make([]ScanFoldersCall, 0), } } -func (m *MockScanner) ScanAll(_ context.Context, fullScan bool) ([]string, error) { +func (m *mockScanner) ScanAll(_ context.Context, fullScan bool) ([]string, error) { m.mu.Lock() defer m.mu.Unlock() @@ -370,7 +370,7 @@ func (m *MockScanner) ScanAll(_ context.Context, fullScan bool) ([]string, error return nil, nil } -func (m *MockScanner) ScanFolders(_ context.Context, fullScan bool, targets []ScanTarget) ([]string, error) { +func (m *mockScanner) ScanFolders(_ context.Context, fullScan bool, targets []ScanTarget) ([]string, error) { m.mu.Lock() defer m.mu.Unlock() @@ -386,7 +386,7 @@ func (m *MockScanner) ScanFolders(_ context.Context, fullScan bool, targets []Sc return nil, nil } -func (m *MockScanner) Status(_ context.Context) (*StatusInfo, error) { +func (m *mockScanner) Status(_ context.Context) (*StatusInfo, error) { m.mu.Lock() defer m.mu.Unlock() @@ -395,19 +395,19 @@ func (m *MockScanner) Status(_ context.Context) (*StatusInfo, error) { }, nil } -func (m *MockScanner) GetScanAllCallCount() int { +func (m *mockScanner) GetScanAllCallCount() int { m.mu.Lock() defer m.mu.Unlock() return len(m.scanAllCalls) } -func (m *MockScanner) GetScanFoldersCallCount() int { +func (m *mockScanner) GetScanFoldersCallCount() int { m.mu.Lock() defer m.mu.Unlock() return len(m.scanFoldersCalls) } -func (m *MockScanner) GetScanFoldersCalls() []ScanFoldersCall { +func (m *mockScanner) GetScanFoldersCalls() []ScanFoldersCall { m.mu.Lock() defer m.mu.Unlock() // Return a copy to avoid race conditions @@ -416,14 +416,14 @@ func (m *MockScanner) GetScanFoldersCalls() []ScanFoldersCall { return calls } -func (m *MockScanner) Reset() { +func (m *mockScanner) Reset() { m.mu.Lock() defer m.mu.Unlock() m.scanAllCalls = make([]ScanAllCall, 0) m.scanFoldersCalls = make([]ScanFoldersCall, 0) } -func (m *MockScanner) SetScanning(scanning bool) { +func (m *mockScanner) SetScanning(scanning bool) { m.mu.Lock() defer m.mu.Unlock() m.scanningStatus = scanning