From a2a92236bc16905ebd7866ceee65206755101685 Mon Sep 17 00:00:00 2001 From: "russell@unturf.com" Date: Mon, 1 Jun 2026 17:45:04 -0400 Subject: [PATCH] SessionsView: isolation_level=None so the viz sees fresh REPL writes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Python sqlite3's default ("legacy" / DEFERRED) isolation mode opens an implicit read transaction on the first SELECT and holds it until commit() / rollback(). For a long-lived viz connection that's a read snapshot pinned at startup — when the REPL writes a new node in another process, the viz keeps returning yesterday's view until the viz process restarts. Setting isolation_level=None puts the connection in autocommit: each SELECT runs in its own implicit transaction that ends as soon as the cursor is consumed, so the next call picks up any WAL frames the writer committed in between. Surfaced by fox writing a turn in `make session` and seeing /sessions api/find return only OLDER sessions — the new node was in nodes_fts (confirmed via direct sqlite3 CLI query) but invisible through the viz's cached SessionsView. Restarting the viz "fixed" it, which is the classic shape of this pin. Read-seam tests still pass (9/9). The cost of autocommit is one extra syscall per SELECT to start/end the implicit transaction — negligible for the viz's request volume. --- arborist/read.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/arborist/read.py b/arborist/read.py index b10f9fa..df44e90 100644 --- a/arborist/read.py +++ b/arborist/read.py @@ -1105,6 +1105,16 @@ class SessionsView: "file:{0}?mode=ro".format(path), uri=True, check_same_thread=False, ) + # Autocommit: every SELECT runs in its own implicit + # transaction that ends as soon as the cursor is consumed. + # Without this, Python's sqlite3 default ("legacy" mode) + # opens an implicit read transaction on the first SELECT + # and holds it until commit/rollback — pinning the + # connection to a stale WAL snapshot when another process + # (the REPL writer) is committing live. The viz needs to + # see fresh writes from the user's REPL session without a + # restart. + self._conn.isolation_level = None self._conn.row_factory = sqlite3.Row except Exception as exc: log.warning("arborist.read.sessions: open failed for %s: %s",