fix: skip db boot init in test env to prevent parallel worker lock
Vitest runs test files in parallel workers. Each worker imports server/db.js, which triggered module-level init(DEFAULT_PATH) unconditionally. Two workers racing to open the same SQLite file caused "database is locked", followed by process.exit(1) killing the worker — surfacing as: Error: process.exit unexpectedly called with "1" Fix: guard the boot init block behind NODE_ENV !== 'test'. Vitest sets NODE_ENV=test automatically. Each worker's beforeEach(() => _resetForTest()) initialises its own :memory: database, so no file coordination is needed. process.exit(1) is also guarded by the same condition — it must never fire inside a test runner process. TDD: two regression tests added to tests/db.test.js documenting the expected boot behaviour and proving the module loads cleanly in parallel. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
15
server/db.js
15
server/db.js
@@ -133,5 +133,18 @@ export function _resetForTest() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ── Boot ──────────────────────────────────────────────────────────────────────
|
// ── Boot ──────────────────────────────────────────────────────────────────────
|
||||||
|
// Skipped in test environment — parallel Vitest workers would race to open
|
||||||
|
// the same file, causing "database is locked". _resetForTest() in beforeEach
|
||||||
|
// handles initialisation for every test worker using :memory: instead.
|
||||||
|
|
||||||
init(process.env.DB_PATH ?? DEFAULT_PATH);
|
if (process.env.NODE_ENV !== 'test') {
|
||||||
|
const DB_PATH = process.env.DB_PATH ?? DEFAULT_PATH;
|
||||||
|
try {
|
||||||
|
init(DB_PATH);
|
||||||
|
} catch (e) {
|
||||||
|
console.error('[catalyst] fatal: could not open database at', DB_PATH);
|
||||||
|
console.error('[catalyst] ensure the data directory exists and is writable by the server process.');
|
||||||
|
console.error(e);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -165,3 +165,23 @@ describe('deleteInstance', () => {
|
|||||||
expect(getInstance(2)).not.toBeNull();
|
expect(getInstance(2)).not.toBeNull();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// ── Test environment boot isolation ───────────────────────────────────────────
|
||||||
|
|
||||||
|
describe('test environment boot isolation', () => {
|
||||||
|
it('vitest runs with NODE_ENV=test', () => {
|
||||||
|
// Vitest sets NODE_ENV=test automatically. This is the guard condition
|
||||||
|
// that prevents the boot init() from opening the real database file.
|
||||||
|
expect(process.env.NODE_ENV).toBe('test');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('db module loads cleanly in parallel workers without locking the real db file', () => {
|
||||||
|
// Regression: the module-level init(DEFAULT_PATH) used to run unconditionally,
|
||||||
|
// causing "database is locked" when multiple test workers imported db.js at
|
||||||
|
// the same time. process.exit(1) then killed the worker mid-suite.
|
||||||
|
// Fix: boot init is skipped when NODE_ENV=test. _resetForTest() handles setup.
|
||||||
|
// Reaching this line proves the module loaded without calling process.exit.
|
||||||
|
expect(() => _resetForTest()).not.toThrow();
|
||||||
|
expect(getInstances()).toEqual([]);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user