fix: prevent search index build from starving library scan for DB access

The search index build and library scan both write to the same
single-connection SQLite DB. The index build runs continuous batch
transactions that can starve the scan's clearLibraryTables call,
causing the scan to silently hang without logging.

Fix: decouple index build from SetContext. The build now starts
AFTER the soft scan completes on startup. For full rescans, the
PreClear hook stops the index build, and PostScan restarts it.

Also made StartBuild/StopBuild safe for multiple calls:
- StartBuild is a no-op if already running
- StopBuild is a no-op if not running (no deadlock on done channel)
- done channel created per-build, not in constructor
This commit is contained in:
2026-03-26 15:21:01 -04:00
parent 71516df651
commit bb015092d4
3 changed files with 60 additions and 8 deletions
+15 -2
View File
@@ -198,8 +198,17 @@ func (yj *YellowJacketApp) OnStartup(ctx context.Context) {
// orchestrate queue clearing and playlist restoration
// without depending on those packages directly.
yj.library.SetRescanHooks(library.RescanHooks{
PreClear: yj.queue.Clear,
PostScan: yj.playlist.RestoreAllPlaylists,
PreClear: func() {
yj.queue.Clear()
// Stop the search index build so it doesn't fight
// with the rescan for DB access.
yj.explore.StopIndexBuild()
},
PostScan: func() {
yj.playlist.RestoreAllPlaylists()
// Restart the index build now that the scan is done.
yj.explore.StartIndexBuild()
},
})
// Wire scan hooks so the playlist service can resolve
@@ -319,5 +328,9 @@ func (yj *YellowJacketApp) OnDomReady(ctx context.Context) {
if err := yj.library.SoftScanAllLibraries(); err != nil {
yj.logger.Error("soft scan failed", "err", err)
}
// Start the explore search index build AFTER the library
// scan completes so they don't fight for DB access.
yj.explore.StartIndexBuild()
}()
}