perf: optimize cross-library move detection for single-library setups (#4888)
* feat: skip cross-library detection for single library setup When only one library is configured, skip the cross-library move detection stage entirely as there are no other libraries to search in. This eliminates unnecessary database queries - the primary performance issue reported by users (5-6 hour scans with 13.5k missing files). Implementation: - Added library count check in processCrossLibraryMoves - Returns input unchanged when len(state.libraries) == 1 - Logs debug message for troubleshooting * refactor: use lightweight queries for cross-library move detection Replace selectMediaFile() with newSelect() in FindRecentFilesByMBZTrackID and FindRecentFilesByProperties. These queries only need basic media file columns for hash and path comparisons, not annotations/bookmarks. Benefits: - Removes unnecessary LEFT JOINs with annotation and bookmark tables - Reduces query overhead for cross-library file matching - Follows existing pattern used by GetMissingAndMatching The annotation/bookmark joins are user-specific (using loggedUser context) and unused in cross-library matching logic where only Equals() and IsEquivalent() checks are performed. * test: add coverage for single-library and multi-library cross-library detection Add test cases to verify: 1. Single-library setup correctly skips cross-library move detection 2. Multi-library setup continues to process cross-library moves Implementation: - New test verifies processCrossLibraryMoves returns input unchanged for single library - Wrapped existing multi-library tests in Context with multiple libraries setup - Ensures no regressions in multi-library matching behavior Tests verify: - Single-library: no database queries, input passed through unchanged - Multi-library: cross-library matching still works correctly - Reduces the likelihood of introducing single-library skip bugs in future * fix: enhance cross-library detection by introducing totalLibraryCount Signed-off-by: Deluan <deluan@navidrome.org> --------- Signed-off-by: Deluan <deluan@navidrome.org>
This commit is contained in:
+7
-5
@@ -28,11 +28,12 @@ type scannerImpl struct {
|
||||
|
||||
// scanState holds the state of an in-progress scan, to be passed to the various phases
|
||||
type scanState struct {
|
||||
progress chan<- *ProgressInfo
|
||||
fullScan bool
|
||||
changesDetected atomic.Bool
|
||||
libraries model.Libraries // Store libraries list for consistency across phases
|
||||
targets map[int][]string // Optional: map[libraryID][]folderPaths for selective scans
|
||||
progress chan<- *ProgressInfo
|
||||
fullScan bool
|
||||
changesDetected atomic.Bool
|
||||
libraries model.Libraries // Store libraries list for consistency across phases
|
||||
targets map[int][]string // Optional: map[libraryID][]folderPaths for selective scans
|
||||
totalLibraryCount int // Total number of libraries (unfiltered), for cross-library move detection
|
||||
}
|
||||
|
||||
func (s *scanState) sendProgress(info *ProgressInfo) {
|
||||
@@ -73,6 +74,7 @@ func (s *scannerImpl) scanFolders(ctx context.Context, fullScan bool, targets []
|
||||
state.sendWarning(fmt.Sprintf("getting libraries: %s", err))
|
||||
return
|
||||
}
|
||||
state.totalLibraryCount = len(allLibs)
|
||||
|
||||
if len(targets) > 0 {
|
||||
// Selective scan: filter libraries and build targets map
|
||||
|
||||
Reference in New Issue
Block a user