music indexer: cache-format version → full rebuild for posters/lyrics migration
Videos/tracks indexed before posters+lyrics existed were skipped by the per-album `v` check (unchanged v → skip), so their posters/ and lyrics/ never generated — a plain reindex couldn't fix it. Add CACHE_VERSION (now 2). The `v` skip is only trusted when the on-disk manifest is already at the current format; an older version forces a one-time FULL rebuild that regenerates every album (incl. the new posters/lyrics), then writes version:2 so subsequent builds skip normally. Verified: old-cache rebuild regenerates the poster, next build skips (no loop). Deploy = restart officer-music, then one reindex (a full rebuild, slower than an incremental — one time only). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -34,6 +34,11 @@ const COVER_FILES = ['folder.jpg', 'cover.jpg', 'folder.png', 'cover.png'];
|
||||
const DISCO_FILE = '_discography.md';
|
||||
const TRACK_CONCURRENCY = 6;
|
||||
const COVER_MAX_PX = 600;
|
||||
// Cache-format version. Bump when the build produces NEW per-album outputs (so far: v2 added video
|
||||
// posters + lyrics). A manifest written by an older CACHE_VERSION forces a one-time FULL rebuild — the
|
||||
// per-album `v` skip only applies once the cache is already at the current format.
|
||||
// v1 → initial (meta + cover) v2 → + posters/ + lyrics/
|
||||
const CACHE_VERSION = 2;
|
||||
|
||||
// ── Types (meta.json matches the app's IndexMeta/IndexTrack) ──
|
||||
|
||||
@@ -445,7 +450,7 @@ export async function buildMusicIndex(): Promise<IndexStatus> {
|
||||
console.log('[music] resync started');
|
||||
|
||||
const prev = await loadManifest();
|
||||
const next: Manifest = { version: 1, generatedAt: status.startedAt!, albums: {} };
|
||||
const next: Manifest = { version: CACHE_VERSION, generatedAt: status.startedAt!, albums: {} };
|
||||
|
||||
try {
|
||||
await mkdir(CACHE_ROOT, { recursive: true });
|
||||
@@ -584,7 +589,10 @@ async function walk(dirAbs: string, prev: Manifest, next: Manifest): Promise<voi
|
||||
].filter((f): f is string => f !== null);
|
||||
const outputsExist = expected.every((f) => existsSync(join(cacheDir, f)));
|
||||
|
||||
if (prev.albums[rel]?.v === v && outputsExist) {
|
||||
// Only trust the per-album `v` skip once the cache is already at the current format — an older
|
||||
// CACHE_VERSION means new outputs (posters/lyrics) may be missing, so rebuild every folder once.
|
||||
const formatCurrent = prev.version === CACHE_VERSION;
|
||||
if (formatCurrent && prev.albums[rel]?.v === v && outputsExist) {
|
||||
status.albumsSkipped += 1;
|
||||
} else {
|
||||
await mkdir(cacheDir, { recursive: true });
|
||||
|
||||
Reference in New Issue
Block a user