-
Notifications
You must be signed in to change notification settings - Fork 4
Description
Problem
When both better-sqlite3 (JS) and rusqlite (Rust) connections are open to the same WAL-mode database file, NativeDatabase.bulkInsertNodes() corrupts the DB. Subsequent reads from either connection fail with SqliteError: database disk image is malformed or disk I/O error.
Context
The native insert path in insert-nodes.ts was never operational — it always crashed during napi-rs serialization due to null visibility values being passed to Option<String> fields (fixed in #693). Once the serialization was fixed, the Rust code actually executed for the first time and revealed the dual-connection WAL corruption.
Reproduction
In CI (where the native binary is available), any test that calls buildGraph with engine: 'native' triggers the issue:
tests/builder/pipeline.test.ts—SQLITE_CORRUPTwhen reading after native inserttests/integration/build.test.ts—disk I/O erroron incremental rebuilds
All pass locally when only the WASM engine is available (native path falls through to JS).
Root cause
The build pipeline holds ctx.db (better-sqlite3) and ctx.nativeDb (rusqlite NativeDatabase) open simultaneously. Both connect to the same .codegraph/graph.db file in WAL mode. When rusqlite writes inside bulkInsertNodes, it may conflict with the JS connection's WAL state.
Fix options
- Close the JS connection before calling native insert, reopen after
- Route all pipeline writes through the native connection when available (remove dual-connection pattern)
- Use exclusive locking mode for the native transaction
Workaround
PR #693 disables tryNativeInsert when ctx.db is open (which is always the case in the pipeline), restoring the pre-existing JS-only behavior.