diff --git a/src/servers/sidecar/music/index.ts b/src/servers/sidecar/music/index.ts index 7342b3fa..8454c358 100644 --- a/src/servers/sidecar/music/index.ts +++ b/src/servers/sidecar/music/index.ts @@ -7,6 +7,7 @@ import { startNightlyReindex, stopNightlyReindex } from './nightly-reindex'; import { startMusicWatcher, stopMusicWatcher } from './watcher'; import { reindexNow, + reindexFull, ensureCacheSetup, MUSIC_ROOT, getIndexStatus, @@ -49,7 +50,9 @@ const DATA_PATH = process.env.DATA_PATH ?? join(process.cwd(), 'data'); // "" } }, Type ∈ Studio/Live/Compilation/Single/EP/… // ETag: ; If-None-Match → 304. Source: each artist folder's // _discography.md (normalized; the md itself is never modified). -// POST /reindex run the build to COMPLETION, then return the final IndexStatus. +// POST /reindex[?full=1] run the build to COMPLETION, then return the final IndexStatus. +// default = incremental (skips unchanged); ?full=1 = full staged +// rebuild + atomic swap (backfill a meta-format change). // GET /reindex/status IndexStatus snapshot. // GET /reindex/stream SSE. Triggers a build if idle (`?trigger=0` = watch-only). // `event: progress` (IndexStatus) throttled ~200ms, then one @@ -112,10 +115,13 @@ const server = Bun.serve({ // ── Index build ── if (url.pathname === '/reindex') { if (req.method !== 'POST') return new Response('Method not allowed', { status: 405 }); - // Run the resync to completion, THEN respond — so the caller's manifest read right after is fresh. - // Incremental builds are near-instant (unchanged albums skip by version stamp). reindexNow joins - // an in-flight build rather than starting a second. - const result = await reindexNow(); + // Run to completion, THEN respond — so the caller's manifest read right after is fresh. Both join an + // in-flight build rather than starting a second. + // default : incremental — near-instant, skips unchanged albums by version stamp. + // ?full=1 : full from-scratch rebuild into a fresh slot, swapped in atomically (staged + safe) — + // use to backfill a meta-format change (e.g. a new track field) across the WHOLE library. + const full = url.searchParams.get('full') === '1' || url.searchParams.get('full') === 'true'; + const result = await (full ? reindexFull() : reindexNow()); return json(result); } if (url.pathname === '/reindex/status') return json(getIndexStatus());