feat(11-01): per-library scan pipeline with queue coordinator

Task 1: Schema, events, and progress types
- Add library_id to CreateAudioFile SQL INSERT and regenerate sqlc code
- Add LibraryScanQueued and LibraryScanQueueDrained event constants
- Regenerate TypeScript events via genevents
- Add LibraryID, LibraryName, QueuedCount to ScanProgress
- Add LibraryID, LibraryName to ScanMetrics
- Add libraryID field to importResult for threading through pipeline

Task 2: Scan queue coordinator and per-library scanning
- Create scan_queue.go with ScanLibrary(id), ScanAllLibraries()
- Add CancelCurrentScan(), CancelAllScans() for queue-aware cancellation
- FIFO scan queue with silent dedup (same library already scanning or queued)
- Refactor Scan() -> scanInternal(libraryID, libraryName, libraryPath)
- Replace GetAllAudioFiles with GetAudioFilesByLibrary for per-library loading
- Thread libraryID through DB writer to set CreateAudioFileParams.LibraryID
- drainQueue auto-starts next queued library or emits LibraryScanQueueDrained
- Pause freezes current scan AND queue
- Add GetScanQueueLength() and QueuedLibraryNames() for UI
- Mark CancelScan() and Scan() as deprecated
This commit is contained in:
2026-03-09 16:02:54 -04:00
parent 68463f3549
commit 943db1cf27
11 changed files with 357 additions and 59 deletions
+4
View File
@@ -38,6 +38,10 @@ export const Events = {
LibraryScanCancelled: "LibraryScanCancelled",
LibraryScanPaused: "LibraryScanPaused",
LibraryScanResumed: "LibraryScanResumed",
// Scan queue events
LibraryScanQueued: "LibraryScanQueued",
LibraryScanQueueDrained: "LibraryScanQueueDrained",
} as const;
export type EventName = (typeof Events)[keyof typeof Events];