Repository navigation
fix(server): enforce event stream ownership and diagnostics - #37585
Closed
armancharan wants to merge 27 commits into
Closed
armancharan wants to merge 27 commits into
armancharan wants to merge 27 commits into
Conversation
Co-authored-by: Cursor <[email protected]>
Co-authored-by: Cursor <[email protected]>
Co-authored-by: Cursor <[email protected]>
Co-authored-by: Cursor <[email protected]>
Narrow unknown event data with object/`in` checks so sessionID is read without an assertion. Co-authored-by: Cursor <[email protected]>
Helpers only need directory; no test supplies a workspace. Co-authored-by: Cursor <[email protected]>
No test supplies a workspace; avoid an unnecessary brand cast. Co-authored-by: Cursor <[email protected]>
Filter interested subscribers once before encode, require directory for location scope (reject workspace-only queries), and cover those cases in tests. Co-authored-by: Cursor <[email protected]>
Collect matching subscribers first so encode/offer share one pass. Co-authored-by: Cursor <[email protected]>
Extract pure interest helpers and cover subscribeInput/equality plus ClientProvider.event.scope reconnecting only when interest changes. Co-authored-by: Cursor <[email protected]>
Serialize TUI subscribe generations, cancel SSE readers on abort, bridge Bun disconnects so EventFeed queues release, and expose content-free feed counters for leak detection. Co-authored-by: Cursor <[email protected]>
Avoid a hard EventFeed.Service requirement on the debug handler so CLI serve Effect inference stays compatible with the runtime handler map. Co-authored-by: Cursor <[email protected]>
Contributor
|
Thanks for your contribution! This PR doesn't have a linked issue. All PRs must reference an existing issue. Please:
See CONTRIBUTING.md for details. |
Contributor
|
The following comment was made by an LLM, it may be inaccurate: Based on my search, the PRs found are all explicitly mentioned as related work in PR #37585's description (parent stack and sibling work under #36441). These are not duplicates but intentionally related:
No duplicate PRs found |
3 of 6 tasks
armancharan
commented
Jul 18, 2026
Replace the hand-rolled unknown guards with decodeUnknownOption so ephemeral sessionID extraction matches host Schema patterns. Co-authored-by: Cursor <[email protected]>
armancharan
marked this pull request as draft
July 18, 2026 02:09
Map HttpApi-decoded ctx.query through interestFromSubscribeQuery, and route deepObject URLSearchParams through the same Schema before building Interest. Co-authored-by: Cursor <[email protected]>
Also derive EventFeed.Diagnostics from the protocol Schema and lock the generation boundary so prior-generation event IDs are not delivered. Co-authored-by: Cursor <[email protected]>
armancharan
commented
Jul 18, 2026
One test was asserting connect, interest change, and no-op scope together. Split into three named cases with a shared mount helper. Co-authored-by: Cursor <[email protected]>
Co-authored-by: Cursor <[email protected]>
armancharan
marked this pull request as ready for review
July 18, 2026 02:44
Co-authored-by: Cursor <[email protected]>
armancharan
commented
Jul 18, 2026
armancharan
commented
Jul 18, 2026
This was referenced Jul 18, 2026
Author
|
Closing this. The change set is too large to review against current |
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.
Issue for this PR
Closes #36445
#36445
Parent: #36441
Related: #36311 (minimal Bun SSE disconnect bridge on the event path only — not a platform-wide fix)
✧ raised · ○ in review · ● approved · ✓ merged
#36441 epic: scope streams + bound payloads
Merge in order:
v2
└ ○ #37486 location interest
└ ○ #37487 session interest + fan-out bench
└ ○ #37585 stream ownership / diagnostics ← this PR
└ ○ #37586 reconnect herd
Siblings under the epic (not git parents of the stack tip):
└ ○ #37559 session blobs + payloadHash
└ ○ #37570 ensure-on-first-failure → feeds #37586
Stacked on #37487 (
fix/event-subscription-sessions). GitHub base isv2because the parent branch is fork-only; ownership-only diff: armancharan/opencode@fix/event-subscription-sessions...event-stream-ownership — retarget base onto that branch after #37487 merges (or when the branch exists on anomalyco).Type of change
What does this PR do?
Guarantees one active event stream per TUI generation, prompt resource release on failure/teardown, and content-free diagnostics for leak detection.
AbortControlleron every exit; reconnect wait1000 + random(0..500)ms so N clients do not phase-lockresponse.body) so Bun sees client disconnect under custom fetchEventFeed.diagnostics()counters (active/opens/closes/serializedEvents/serializedBytes/overflows); debugGET /api/debug/event-feed; IncomingMessageaborted/close→ServerResponse.destroy()soacquireReleaseruns (2.0: standalone SSE disconnect can wedge Bun server at 100% CPU #36311 bridge, event path only)How did you verify your code works?
packages/servertest/event-feed.test.ts— eleven-client churn → baseline; overflow counts; content-free dumppackages/servertest/event-feed-fanout.bench.test.ts— from stack base: fan-out accounting laws (clients × sizes)packages/servertest/event-feed-ownership.test.ts— scope cancel → baseline; real-socket abort closes body; eleven sequential scopes never accumulatepackages/tuitest/cli/tui/client-ownership.test.tsx— rapid interest ≤1 stream; teardown → 0; prior generation does not receive events after reconnectpackages/tuitest/cli/tui/client-scope.test.tsx— connect / reconnect on change / no-op when unchanged (split)packages/server,packages/tui, andpackages/cliAcceptance → test
teardown leaves zero active event streams+rapid interest changes never exceed one active event streamrapid interest changes never exceed one active event streamreturns active subscriber count to baseline when scopes close after eleven-client churn+eleven sequential subscribe scopes never accumulate active subscriberscanceling a subscriber scope…+aborting a real Node HTTP client returns EventFeed.active to baselineevent IDs from a prior generation are not delivered after interest reconnectreturns active…dump asserts + overflow countersScreenshots / recordings
N/A — not a UI layout change.
Checklist