Fix build SQLITE_BUSY: busy_timeout before a best-effort WAL switch

lib/db.ts switched to WAL at module load before setting busy_timeout.
next build imports it from several workers while the live server holds
the same file, and a journal-mode change needs the file to itself — so
the pragma failed instantly with SQLITE_BUSY and took the whole build
down ("Failed to collect page data"), blocking updates on any box whose
database was still in rollback mode. The timeout is now set first and
the WAL switch is wrapped: a held file keeps its current mode.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Brandon Li
2026-09-22 22:07:38 -05:00
co-authored by Claude Opus 5.5
parent d462cc284f
commit 1d4d45bd79
2 changed files with 15 additions and 4 deletions
+10 -3
View File
@@ -13,10 +13,17 @@ mkdirSync(path.dirname(DB_PATH), { recursive: true });
const db = new Database(DB_PATH);
db.pragma('foreign_keys = ON');
// If two processes are ever misconfigured onto the same file, WAL + a busy
// timeout turns SQLITE_BUSY crashes into brief contention.
db.pragma('journal_mode = WAL');
// Timeout first: every later statement, including the journal switch below,
// waits out a concurrent holder instead of failing with SQLITE_BUSY.
db.pragma('busy_timeout = 5000');
// WAL is best-effort. Switching journal mode needs the file to itself, and
// `next build` imports this module from several workers while the live server
// still holds the same file — a hard failure here fails the whole build.
try {
db.pragma('journal_mode = WAL');
} catch {
// Another connection holds the file; keep its journal mode.
}
db.exec(`
CREATE TABLE IF NOT EXISTS instruments (