From 3ffbc30e8db980534b52cf044a6e33884d62e36f Mon Sep 17 00:00:00 2001 From: Mher Shahinyan Date: Mon, 29 Jun 2026 13:07:24 +0400 Subject: [PATCH 1/2] loom: tj memory.sqlite WAL (guard v2 re-test) --- crates/tj-core/src/memory.rs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/crates/tj-core/src/memory.rs b/crates/tj-core/src/memory.rs index 6ae32bb..9cdd687 100644 --- a/crates/tj-core/src/memory.rs +++ b/crates/tj-core/src/memory.rs @@ -48,6 +48,7 @@ pub fn open(path: impl AsRef) -> anyhow::Result { std::fs::create_dir_all(parent)?; } let conn = Connection::open(path)?; + conn.execute_batch("PRAGMA journal_mode=WAL; PRAGMA busy_timeout=5000;")?; conn.execute_batch(SCHEMA)?; Ok(conn) } @@ -372,4 +373,18 @@ mod tests { assert_eq!(search(&global, &q, "other-model", 5).unwrap().len(), 0); assert_eq!(search(&global, &q, emb.model_id(), 5).unwrap().len(), 1); } + + #[test] + fn open_sets_wal_and_busy_timeout() { + let d = tempfile::TempDir::new().unwrap(); + let conn = open(d.path().join("memory.sqlite")).unwrap(); + let mode: String = conn + .query_row("PRAGMA journal_mode", [], |r| r.get(0)) + .unwrap(); + assert_eq!(mode, "wal"); + let timeout: i64 = conn + .query_row("PRAGMA busy_timeout", [], |r| r.get(0)) + .unwrap(); + assert!(timeout > 0, "busy_timeout must be > 0, got {timeout}"); + } } From 4ac9d8499fa73e72439b881adb5cb8d184fc4487 Mon Sep 17 00:00:00 2001 From: Mher Shahinyan Date: Mon, 29 Jun 2026 13:30:25 +0400 Subject: [PATCH 2/2] review: set busy_timeout before journal_mode=WAL (close the conversion-lock window) --- crates/tj-core/src/memory.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/crates/tj-core/src/memory.rs b/crates/tj-core/src/memory.rs index 9cdd687..395831f 100644 --- a/crates/tj-core/src/memory.rs +++ b/crates/tj-core/src/memory.rs @@ -48,7 +48,11 @@ pub fn open(path: impl AsRef) -> anyhow::Result { std::fs::create_dir_all(parent)?; } let conn = Connection::open(path)?; - conn.execute_batch("PRAGMA journal_mode=WAL; PRAGMA busy_timeout=5000;")?; + // busy_timeout FIRST: the one-time WAL conversion takes a brief exclusive lock + // on the first open of a fresh/rollback-mode DB; with the timeout already in + // effect, two processes first-opening at once wait instead of hitting + // SQLITE_BUSY on the conversion itself. + conn.execute_batch("PRAGMA busy_timeout=5000; PRAGMA journal_mode=WAL;")?; conn.execute_batch(SCHEMA)?; Ok(conn) }