perf(ws): scope preview frames and drop repeated shell payloads - #298
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
593527e to
2cd3105
Compare
|
Comments Outside DiffThese findings sit on lines the diff does not cover, so they could not be posted inline. Each one leaves this list once its file changes.
|
4557508 to
f537d9c
Compare
Preview frames went to every client regardless of thread; the subscription now filters by threadId server-side. Shell subscriptions skip upserts equal to the last one sent, config subscribes no longer force provider probes or broadcast unchanged lists, and stream budgets charge the slim payloads clients actually receive. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Background probes that only moved checkedAt were no longer broadcast, so Settings showed a stale last-check time. Completed probes now publish a new checkedAt; snapshot re-syncs stay quiet. Concurrent server-config subscriptions could each queue a probe for the same stale provider. A server-wide in-flight set now probes each stale instance once per burst. Dropping unchanged shell upserts also froze the client's resume cursor, so a long run of unchanged events pushed reconnects past the replay window. An unchanged shell is re-sent once the cursor would lag 500 events. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Subscription-triggered provider probes are deduplicated across connections, but each ran in the scope of the subscription that started it. When that client disconnected, the probe was cancelled while other clients waited on it. The probes now run in the server's scope. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
A slow background provider probe could finish after a newer explicit refresh and overwrite its fresh status with stale data. ProviderRegistry now stamps each probe of an instance with a start generation and only applies a result if no newer probe of that instance has already landed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
65d4763 to
dcbf4a6
Compare
Change-stream results skipped the probe generation guard, so a late stream item could overwrite a newer explicit refresh, and one global semaphore serialized applies across unrelated instances. Probe and stream results now keep the snapshot with the newest checkedAt, decided inside the providers Ref.modify, so no lock is needed. A stored checkedAt in the future never blocks, in case the clock moved back. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Instances without a driver cannot be probed, so their checkedAt never advanced and every subscription past the TTL scheduled a no-op refresh for them. The shell dedup test also drops its timeout, since it already waits on a known sequence of events. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Stacked on perf/server-hot-paths.
The WebSocket layer sent far more than clients needed, which matters most over SSH, Tailscale, and tunnels. Bot browser preview frames, full-viewport PNGs of 100 KB to 1 MB as base64, went to every subscribed client regardless of which chat owned them, with filtering only in the browser. Every thread event made each client refetch and re-send that thread's shell even when nothing visible changed. Subscribing to server config forcibly re-probed every provider by spawning CLI version checks and always broadcast the result, because the probe timestamp defeated the change comparison. Stream budgets charged the raw event size, so one tool result over 8 MB failed every client's shell subscription at once.
The preview subscription now takes an optional threadId and the server filters frames before serialization, an additive contract change that keeps old clients working. Shell subscriptions remember the last shell sent per thread and drop identical refetches. Config subscribes serve the cached provider snapshot, re-probing only entries older than 60 seconds, and the change comparison ignores probe timestamps. The shell stream stores slim thread references instead of raw events, and activity slimming is cached per event so it runs once regardless of subscriber count.
Verified with 210 passing tests across six suites, including new tests for preview scoping and shell de-duplication, with the dedupe test confirmed to fail when the fix is disabled. The preview event queue deliberately stays unbounded because a sliding queue could drop lifecycle events and desync clients.
Created with Claude Fable 5.1 in Claude Code.
🤖 Generated with Claude Code