Skip to content

feat: End a stream with an error when neither an event nor a heartbeat arrives for 30 seconds. - #413

Merged
goloroden merged 1 commit into
mainfrom
feat/heartbeat-timeout
Oct 3, 2026
Merged

goloroden merged 1 commit into
mainfrom
feat/heartbeat-timeout

Conversation

@goloroden

Copy link
Copy Markdown
Member

The server sends a heartbeat every second on the streams of observeEvents and runEventQlQuery. If the connection stalls without being closed (for example behind a proxy that keeps it open but passes nothing anymore), the client waited until Node's fetch gave up after five minutes with a generic TypeError: terminated, and an application observing events kept believing it was live until then. The same change is made in all seven client SDKs.

  • observeEvents and runEventQlQuery now throw the new HeartbeatTimeoutError (an exported class, name 'HeartbeatTimeoutError', "No event and no heartbeat arrived for 30 seconds.") when no line, heartbeat included, arrives for 30 seconds. The SDK cancels the body reader, which closes the socket.
  • Every line restarts the 30 seconds. The timer only runs while the SDK waits for the next line, so the time the caller spends on an event or row does not count.
  • Aborting via AbortSignal or break ends the stream quietly, as before.
  • readEventTypes skips heartbeat lines, but the server never sends any there, so it stays unchanged, as do readEvents and readSubjects.
  • 30 seconds lives in an internal object that the package's exports map does not expose, so the public API only grows by the error class.
  • README: "Detecting a Stalled Connection" after "Aborting a Query" and after "Aborting Observing".

Tests (src/heartbeatTimeout.test.ts, local node:http server, 9 tests): stall → error and the connection closed (with and without a caller signal); heartbeats keep it alive; events and rows in time are delivered; a slow caller gets no timeout; caller abort ends quietly. Red first: both stall tests ran into their 5 s guard. npm run qa green (tsc, biome with --error-on-warnings, 74 tests); npm run build green.

🤖 Generated with Claude Code

https://claude.ai/code/session_01TCdPte6nY6ToUVd2prb9GM

…t arrives for 30 seconds.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TCdPte6nY6ToUVd2prb9GM
@goloroden
goloroden requested a review from a team as a code owner October 3, 2026 21:33
@goloroden goloroden self-assigned this Oct 3, 2026
@goloroden
goloroden merged commit 02e9296 into main Oct 3, 2026
2 checks passed
@goloroden
goloroden deleted the feat/heartbeat-timeout branch October 3, 2026 21:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant