Move thread-list SQLite reads off the serving loop - #4
Merged
Conversation
Synchronous better-sqlite3 on a large db froze every client. File-backed servers now run one readonly WAL worker for thread list and sidebar project+thread reads. In-memory tests and a worker that fails to start keep the existing sync path. Fixes get-bb#1131
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Human comments
What was wrong
better-sqlite3is synchronous. Thread-list and sidebar reads ran on the Node serving loop. One cold query on a 1.7GBbb.dbfroze every client for 11s, including WebSocket token streams. Related: get-bb/bb#1131.What changed
packages/db+apps/server/src/sqlite-read-worker.ts).listThreadsWithPendingInteractionStateOffThread(and the project-scoped variant).:memory:tests and a worker that fails to start keep the existing sync path.dist/sqlite-read-worker.js.Search and timeline reads stay on the serving connection. No protocol change.
Why this way
T3’s second rule: never block the Node serving loop on a synchronous SQLite read. A readonly WAL worker is the smallest move that keeps
better-sqlite3and WAL, and only relocates the queries that already froze the loop (thread list, sidebar).We did not migrate to async sqlite, did not rewrite the schema, and did not move search or timeline yet. Those are more surface area for the same idea. Writes stay on the serving connection; the worker is read-only so it cannot fight the writer.
Benefit to bb
Local and desktop servers with a large db. Token streams, reconnect, and opening another thread keep running while a sidebar query is in flight. A hosted server that uses this worker gives the same to web clients.
Harvest
Independent. Already opened: get-bb/bb#2936.
Decision record: docs/perf-control-plane.md (PR #9).
How you verified
packages/db/test/sqlite-read-queue.test.ts: in-memory stays on the calling connection; a file-backed worker returns the same thread list as the serving connection.Related: get-bb#1131, get-bb#2936