Repository navigation
fix(server): full shell reads leave the main thread, thread usage reads one thread - #339
Merged
Merged
Conversation
…ds one thread - ProjectionStore.getShellSnapshot runs on the SQLite reader worker, so the remaining writer-path callers (worktree branch rename, MCP agent session lists, manager.sessions, startup) no longer block the event loop for ~2 s. - threadUsage.get reads only the requested thread's shell row instead of the full active shell on every open thread view each minute. - AGENTS.md: rules for server code that must scale with bkt3's database. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ute and listLive fallback Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
bk-agent-01
marked this pull request as ready for review
October 21, 2026 16:14
tusharbhardwaj-bk
approved these changes
Oct 21, 2026
Collaborator
Author
|
Merged as bk-agent-01, pinned to the approved head
Next: I check stagebkt3 after the deploy. |
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.
Problem
After #338, some code paths still read all ~1,800 bkt3 threads on the server's main thread. A review of stage
4d6aa7488fagainst the production trace found:ProjectionStore.getShellSnapshotruns on the writer connection, on the event loop. On production, one full read costs about 1.0 s (active threads) to 2.2 s (all threads). Callers that do not addNodeSqliteClient.readOnly:ThreadLaunchServicebranch rename, after each new worktree launch. My estimate is 1–2 per hour, which matches the old baseline of 1–3 stalls per hour.mcp/toolkits/agent/context.tsloadVisibleSessions(whoami,inbox,find_sessions,brief,start_session,wait). Measured 1.0–1.06 s each.manager.sessions,CheckpointRestoreSafety,AgentAwarenessRelay,SessionActivityReactor, startup.threadUsage.getreads the full active shell to find one thread. Each open thread view on each client calls it up to once a minute. Production showed 14 calls in 549 s, with p50 4.4–7.5 s and max 17.7 s end to end.Fix
getShellSnapshotwraps its transaction inNodeSqliteClient.readOnly, so the SQL runs on the reader worker from fix(server): shell reads run on a SQLite reader worker and no longer freeze the server #328. Inside an open write transaction, the read stays on the writer (nodeSqliteClient.ts), so callers that read in a transaction keep the same consistency. Only the decode stays on the main thread. On stage, decode costs about 0.14 ms per row, so my estimate is 110–260 ms on production.threadUsage.getusesgetThreadShellById. To keep the old result for archived threads, the handler still returns no session and no start time for them.AGENTS.md(also loaded throughCLAUDE.md) gets a fork section, "Server code must scale with bkt3's database". It has six rules from the incidents in fix(server): reaper no longer freezes the event loop with unindexed event scans #164, fix(server): pull-request sweep and plan-flag reads no longer freeze the server #325/fix(server): promote the pull-request sweep and plan-flag freeze fix to bkt3 #326, fix(server): shell reads run on a SQLite reader worker and no longer freeze the server #328 and fix(server): account policies no longer freeze the server reading the shell #338.No schema changes, no migrations, no new events. The fork markers are in place.
How I tested
This host runs no tests (the dev-server compute policy). CI runs these on the head:
wsForkHandlers.threadUsage.test.ts: the handler reads one thread shell and never callsgetShellSnapshot. Archived and missing threads keep the empty result.ProjectionStoreand orchestration tests cover thegetShellSnapshotresult. I did not add a reader-routing test, because the routing is the sharedreadOnlyhelper thatnodeSqliteClient.test.tsalready covers.After the merge into
stage, I will check stagebkt3 (stall warnings and probe latency).Risks
Follow-up found in review (older bug, not changed here)
legacyThreadShell(legacyProjection.expbkt3.ts:75) always setssession.providerThreadIdtonull. SothreadUsage.getalways sendssessionIds: [], and thread usage is empty in production, both before and after this PR.Left for later (measured, not worth a change now)
GET /api/orchestration/shellalready uses the reader. The real fix isBRIDGE_T3_EVENT_FEEDin the bridge.🤖 Generated with Claude Code