Skip to content

perf(server): drop duplicate provider session status events - #214

Merged
tusharbhardwaj-bk merged 2 commits into
expbkmainfrom
t3code/perf-1-session-set-dedupe
Sep 26, 2026
Merged

tusharbhardwaj-bk merged 2 commits into
expbkmainfrom
t3code/perf-1-session-set-dedupe

Conversation

@tusharbhardwaj-bk

@tusharbhardwaj-bk tusharbhardwaj-bk commented Sep 26, 2026 •

Copy link
Copy Markdown
Collaborator

Problem

Claude reports system/status: requesting on every model request inside a turn. The Claude adapter maps each one to session.state.changed, and ProviderRuntimeIngestion turned every one into a thread.session.set whose only new value was updatedAt.

In the last 20k prod events, 2,040 of 2,666 thread.session-set (77%) were exact repeats of the previous one apart from updatedAt. One thread had 213 in 3.6 h. Each one costs:

  • an event row and a projection write;
  • a push to every shell and thread subscriber;
  • a replay item on reconnect;
  • for non-running statuses, a ThreadPullRequestReactor sync.

Fix

  • New fork module orchestration/sessionSetDedupe.expbkt3.ts. It skips the dispatch when the next session equals the projected thread.session in status, activeTurnId, lastError, providerThreadId, runtimeMode, providerName and providerInstanceId.
    • The last two are an addition to the audit's list, so a provider or instance switch with the same status is never swallowed.
  • One marked seam in ProviderRuntimeIngestion.ts: the upstream orchestrationEngine.dispatch({ call becomes dispatchSessionSetUnlessNoOp(...)({. The command literal is untouched.
  • Only session.state.changed is filtered. session.started, thread.started, turn.*, session.exited and runtime.error always dispatch.

Why this is safe:

  • Projection writes run inside the dispatch transaction (OrchestrationEngine.ts withTransaction → projectEventDeferred), so the projected session is current when ingestion compares.

  • The readers of session.updatedAt all key off a real transition, which is never dropped:

    • the reaper idle window (ProviderSessionReaper.ts:340);
    • the settled-turn completion time;
    • snooze wake-on-error (ThreadSettlementPolicy.ts:129).
  • Recorded edge case: the fork branch of ProviderSessionReaper keeps a session alive when the adapter still holds a turn but the projection's activeTurnId is null. It does this through latestThreadEventAt within the 30 min threshold. Before this PR, status pings produced session-set events that kept that timestamp fresh; now only real events do. This only matters if the projection has already lost activeTurnId and the agent emits nothing else for 30 min, so it is accepted.

Evidence

Fork test ProviderRuntimeIngestion.expbkt3.test.ts, 10 identical running pings in one burst:

thread.session-set events persisted
before (dedupe disabled) 10
after 1

Real transitions (running → ready → running) and a changed error message still land.

Tests run:

  • NODE_ENV=test vp test run on sessionSetDedupe.expbkt3.test.ts, ProviderRuntimeIngestion.expbkt3.test.ts, and the existing ProviderRuntimeIngestion.test.ts + .approval.test.ts: 89 + 77 pass.
  • vp run typecheck in apps/server is clean.
  • The fork-marker check passes.

After the expbkt3 deploy I will re-count duplicate session-sets on the expbkt3 DB.

Candidate to upstream: the same no-op comparison would help every T3 Code user.

Model/harness: Claude Opus 5.5 via Claude Code in T3 Code.

🤖 Generated with Claude Code


View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need. Autofix is disabled.

Claude reports a status ping on every model request inside a turn, and
ingestion turned each one into a thread.session.set whose only change was
updatedAt (2,040 of 2,666 session-set events in a 3.6 h prod sample).

A fork helper now skips the dispatch for session.state.changed when status,
activeTurnId, lastError, providerThreadId, runtimeMode, providerName and
providerInstanceId all equal the projected session. Lifecycle events always
dispatch.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions github-actions Bot added vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. size:M labels Sep 26, 2026
@github-actions

github-actions Bot commented Sep 26, 2026 •

Copy link
Copy Markdown

Thread transfer impact

✅ Thread transfer remains within every enforced ceiling.

ℹ️ No successful main baseline artifact is available yet. This run establishes the initial measurement.

Provider Metric Main baseline This PR Impact PR ceiling
Codex Total thread wire — 13.8 KiB — 15.1 KiB ✅
Codex Thread snapshot wire — 7.3 KiB — 7.8 KiB ✅
Codex Live turn WebSocket wire — 6.5 KiB — 7.8 KiB ✅
Codex Live turn WebSocket decoded — 57.1 KiB — 66.4 KiB ✅
Codex Live turn messages — 10 — 21 ✅
Claude Total thread wire — 13.8 KiB — 15.1 KiB ✅
Claude Thread snapshot wire — 7.3 KiB — 7.8 KiB ✅
Claude Live turn WebSocket wire — 6.5 KiB — 7.8 KiB ✅
Claude Live turn WebSocket decoded — 57.9 KiB — 66.4 KiB ✅
Claude Live turn messages — 9 — 21 ✅

Baseline: unavailable · PR result: 7ac7f45 · Source CI: success

Scenario and decoded snapshot size

10 historical turns, 5 command tools per turn, 878.9 KiB retained MCP result per historical turn, and a 1.05 MiB retained result in the measured turn.

  • Codex decoded thread snapshot: 114.9 KiB
  • Claude decoded thread snapshot: 115.6 KiB

Updated in place by a trusted workflow. PR artifacts are strictly validated and never executed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@tusharbhardwaj-bk
tusharbhardwaj-bk merged commit 9686119 into expbkmain Sep 26, 2026
22 checks passed
bk-agent-01 added a commit that referenced this pull request Sep 27, 2026
Promote expbkmain: bkt3 performance work (PRs #214–#239)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:M vouch:trusted PR author is trusted by repo permissions or the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants