Skip to content

2.0: Enforce event-stream ownership, cleanup, and diagnostics #36445

Closed

Description

@kitlangton

Parent: #36441

Problem

The generated Promise SSE client cancels its ReadableStream reader after a parser failure, but under Bun 1.3.14 that does not reliably close the underlying HTTP response. The TUI reconnect loop can open a replacement while the server retains the previous response, EventV2.liveBounded listener, and queue.

A real-socket reproduction sends malformed SSE while keeping the response open. The client rejects with MalformedResponse, but the server still reports one active response after cleanup.

Without diagnostics, active response count, event-bus subscriber count, and serialization volume are invisible until CPU and memory become pathological.

Goal

Guarantee one active event stream per client owner, prompt resource release on failure/teardown, and enough bounded diagnostics to identify leaks.

Requirements

  • Define ownership for one mounted TUI and one event-stream generation.
  • Abort or fully dispose the previous transport before opening its replacement.
  • Ensure HTTP response finalization removes the event listener and shuts down its queue.
  • Handle malformed data, oversized events, transport failures, server restarts, and consumer exceptions.
  • Add retry backoff/jitter where synchronized clients would otherwise reconnect in phase.
  • Expose content-free diagnostics for active streams/subscribers, opens/closes, serialized event counts/bytes, overflows, and reconnect reasons.

Acceptance criteria

  • One mounted TUI has exactly one active stream and zero after teardown.
  • Repeated failure/reconnect cycles never exceed one active stream per TUI.
  • Eleven TUI clients produce exactly eleven active streams, not an accumulating count.
  • Cancelling a real network client closes the server response and returns listener count to baseline.
  • Each event ID is handled at most once per TUI generation.
  • Diagnostics expose leaked/overlapping subscriptions without logging payloads.

Activity

  1. added
    bugSomething isn't working
    perfIndicates a performance issue or need for optimization
    coreAnything pertaining to core functionality of the application (opencode server stuff)
    on Jul 11, 2026
  2. HOYALIM commented on Jul 13, 2026

    @HOYALIM

    I reproduced the malformed-SSE cleanup leak on current dev with a real Bun 1.3.14 HTTP socket: the Promise client rejects with MalformedResponse, but the server response remains open after reader.cancel(). There is no overlapping open PR touching packages/httpapi-codegen/src/index.ts or the generated Promise client. I can take a focused first slice that gives each SSE iterator an internal abort controller, aborts the fetch transport on parser exit, regenerates the client, and adds a real-socket regression proving server-side close. This would address transport cleanup only, not close the broader ownership/diagnostics issue. Is that split acceptable, and should it get a focused child issue for the issue-first requirement?

  3. HOYALIM commented on Jul 13, 2026

    @HOYALIM

    Follow-up after prototyping: an internal fetch AbortController plus reader.cancel() still does not close the server response on Bun 1.3.14 in the real-socket regression. The effective mitigation therefore needs the server-side IncomingMessage.aborted -> ServerResponse.destroy() bridge, which overlaps the active claim on #36311. I am withdrawing this client-only slice rather than opening a duplicate or ineffective PR.

  4. self-assigned this
    on Jul 19, 2026
  5. neriousy commented on Oct 21, 2026

    @neriousy
    Member

    Partly done: the root server leak (#36311) was fixed by the Bun upgrade, and the client now shares event streams (packages/client/src/shared-events.ts) and detects stalls (#47571). Stream diagnostics, reconnect backoff with jitter and aborting the transport on parser failure weren't added; #37585 was closed unmerged. Closing this tracker.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

2.0bugSomething isn't workingcoreAnything pertaining to core functionality of the application (opencode server stuff)perfIndicates a performance issue or need for optimizationtui

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions