Implements comprehensive progress tracking for scan jobs to provide real-time
statistics to the frontend (files_scanned, new_items, errors).
Changes:
1. Extended JobResult struct with new fields:
- FilesScanned: total files processed
- NewItems: books added to database
- Errors: scan errors encountered
2. Added progress callback mechanism:
- Job.ProgressCallback function field for real-time updates
- Job.UpdateProgress() method to trigger callbacks
- Worker stores callback and updates JobResult during scan
3. MediaScanner now tracks statistics:
- totalFiles, newItems, errors counters
- GetStats() method to retrieve statistics
- First pass counts total files for progress calculation
- Batches progress updates every 10 files (reduces mutex contention)
- Final update ensures 100% progress is reported
4. Updated processMediaFile signature:
- Returns (bool, error) instead of (error)
- true = new item created, false = existing/updated/error
- Increments newItems counter when creating database entries
- Updated WatchChanges to handle new return value
5. Worker job completion extracts stats:
- Parses result map for files_scanned, new_items, errors
- Stores in final JobResult for API response
6. GetScanStatus API response includes new fields:
- files_scanned, new_items, errors now in JSON response
- Frontend can display real-time progress
Design decisions:
- Batching every 10 files balances performance vs. granularity
- Thread-safe via worker mutex (w.mu.Lock/Unlock)
- Callback pattern decouples scanner from job management
- processMediaFile return type allows tracking new vs. updated items
- Maintains backward compatibility (uses || 0 fallbacks in frontend)
Testing:
- All code compiles successfully
- Follows service layer pattern (no business logic in handlers)
- No database schema changes
- Integration tests to be added in Step 8 (separate commit)
Files modified:
- internal/services/worker.go (JobResult, Job struct, processScanJob, processJob)
- internal/services/media_scanner.go (struct fields, GetStats, ScanFolders, processMediaFile)
- internal/handlers/scanner.go (GetScanStatus response)
Related: TASKS-backend-progress-tracking.md Steps 1-7