Repository navigation
fix(server): ask for a resync after every event-stream overflow - #759
Merged
Ishaan Gangwani (ishaan1124) merged 1 commit intoSep 28, 2026
Conversation
ANIRUDDHA ADAK (aniruddhaadak80)
requested review from
Aayam Bansal (aayambansal) and
Ishaan Gangwani (ishaan1124)
as code owners
September 27, 2026 19:11
|
ANIRUDDHA ADAK (@aniruddhaadak80) is attempting to deploy a commit to the InkVell Team on Vercel. A member of the Team first needs to authorize it. |
The overflow marker was a one-way latch, so only the first overflow on a connection raised the `server.connected` frame that makes the client re-hydrate. A later overflow dropped events with no frame to announce it and the workspace stayed stale until it reloaded. Clear the latch once that frame has been delivered, so every overflow raises its own.
Ishaan Gangwani (ishaan1124)
force-pushed
the
fix/event-stream-overflow-resync
branch
from
September 28, 2026 05:11
c03eed0 to
ed9a1b3
Compare
Ishaan Gangwani (ishaan1124)
merged commit Sep 28, 2026
79da954
into
synthetic-sciences:main
1 check failed
3 of 8 tasks
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.
What does this PR do, and why?
Both event-stream routes keep a bounded per-connection queue and, on overflow,
unshift a
server.connectedframe so the client re-hydrates. Whether thathappens was controlled by a latch that only ever went one way:
state.overflowedwas never cleared, so only the first overflow on aconnection ever raised a resync frame. After the client consumed that one
frame and re-hydrated, a later overflow dropped events with nothing to announce
it — the workspace stayed stale until the tab reloaded.
The fix clears the latch when the resync frame is actually written to the
socket, so each overflow raises its own frame once the previous one has been
delivered:
Applied to both
/event(server.ts) and/global/event(routes/global.ts),which carry the same latch.
Overflows that happen while a resync frame is still queued keep the latch set,
so one pending frame still covers every loss since it was queued — the client
is not asked to re-hydrate twice for the same gap.
No client change is needed: the workspace already treats a
server.connectedarriving mid-stream as a re-hydrate (see
frontend/workspace/src/context/reconnecting-event-stream.test.tsand
global-sync-bootstrap.test.ts).Linked issue
Fixes #756
How did you verify it?
One focused regression per route, both added to the existing files. Each opens
one connection, overflows it, lets the client consume the resync frame and the
whole backlog (so the next overflow starts from an empty queue), then
overflows again on the same connection and requires a second resync frame.
On unmodified
3e94875cboth fail — the second overflow produces no frame, sothe wait runs out:
With the fix, all eight tests in the two files pass, and the two new ones stop
depending on timing (853 ms and 536 ms, against a 30 s budget):
The pre-existing assertions that a single overflow yields exactly two
server.connectedframes still pass, so the change does not add frames to thecommon path.
Also run:
bun run --cwd backend/cli typecheck→ exit 0Select-Stringoverbackend/cli/test/server/*.tsforinternal/eventandglobal/eventreturns only these two files, so nothing else in the serversuite drives the changed routes.
Pre-existing reds on this Windows checkout, not from this diff:
bun run format:checkcannot pass here: git materializes the LF blobs asCRLF, so Prettier flags hundreds of untouched files, including
tsconfig.jsonand
turbo.json. I verified all five changed files are formatted per the repoconfig with line endings normalized.
bun run typecheck: backend is clean;@synsci/workspacefails becausefrontend/workspace/src/custom-elements.d.tsis a symlink (mode120000) thatWindows checked out as a text file containing
../../ui/src/custom-elements.d.ts,which TypeScript then parses as source →
TS1128.I did not run the full
./test/serverdirectory: it exceeded 30 minutes on thismachine, and the grep above bounds the blast radius to the two files I ran.
Checklist
bun run checkis green (format, typecheck, backend + frontend/ui + SDK tests) — blocked on this Windows checkout by the CRLF and symlink artifacts described above; backend typecheck is clean and both changed test files are greenbun run --cwd frontend/workspace buildsucceeds if I touchedfrontend/workspaceorfrontend/ui— not touched./tooling/repo/generate.tswas run and thetooling/sdkoutput committed if I changedbackend/cli/src/server— not needed: no route, schema or response changed, only when an existing frame is queued, so the OpenAPI contract is untouched. Please confirm that reading is right.frontend/docs/src/content/openscience/is updated if behavior changed — no doc change needed: the queue bound and the resync frame already behave this way, this only stops the second one from being suppressedpackage.jsonversions and tags are written by the release workflow)installandfrontend/landing/public/installare still byte-identical if I touched either — not touched