Skip to content

feat!: Report a server-initiated stream close to the error handler - #91

Merged
jsonbailey merged 3 commits into
mainfrom
jb/sdk-3204/report-server-close
Sep 25, 2026
Merged

jsonbailey merged 3 commits into
mainfrom
jb/sdk-3204/report-server-close

Conversation

@jsonbailey

@jsonbailey jsonbailey commented Sep 25, 2026 •

Copy link
Copy Markdown
Contributor

Summary

When the server ends the stream and close was not called, the client now passes an SSE::Errors::StreamClosedByServerError to on_error. The client then reconnects as before.

This follows the WHATWG SSE processing model. On a normal end of body, the client must "reestablish the connection", and that step fires the error event. The Go, Java and Python eventsource libraries already report a server close to the error handler. Before this change, the Ruby gem reconnected silently.

Why now

The Ruby server SDK's RETRY conformance work (SDK-2793) controls the reconnect delay and waits in its error handler. It needs this signal. Without it, a server close reconnects with no delay.

Breaking change

A caller that calls close on any error now stops reconnecting after a server close. Release as 3.0.0.

Testing

  • bundle exec rspec spec: 171 examples, 0 failures.
  • bundle exec rubocop --parallel: 16 files inspected, no offenses.
  • Ruby server SDK (SDK-2793 branch) full contract suite against 03c7b1a, with long-running tests enabled: 4697 tests ran, 0 failed.

Jira

SDK-3204


Note

Overview
Breaking: When the server ends the SSE body (EOF or nil from readpartial), the client now raises SSE::Errors::StreamClosedByServerError and delivers it to on_error before reconnecting, instead of exiting the read loop silently. Aligns with WHATWG SSE and other LaunchDarkly eventsource clients so callers can apply reconnect delay in the error handler.

ReadTimeoutError is unchanged and is not conflated with server close. Client-initiated close still avoids surfacing an error to on_error.

New specs cover EOF/nil paths, timeout vs close, no error on client close, and reconnect when the error handler raises. headers_spec uses the shared send_stream_content helper.

Reviewed by Cursor Bugbot for commit 03536d4. Bugbot is set up for automated code reviews on this repo. Configure here.

When the server ends the stream and close was not called, on_error now
gets an SSE::Errors::StreamClosedError. The client reconnects as before.
This follows the WHATWG SSE processing model, where a normal end of body
fires error before it reestablishes the connection.

BREAKING CHANGE: A caller that calls close on any error now stops reconnecting after a server close.
@jsonbailey
jsonbailey marked this pull request as ready for review September 25, 2026 20:06
@jsonbailey
jsonbailey requested a review from a team as a code owner September 25, 2026 20:06
@jsonbailey
jsonbailey merged commit 7e4dc1b into main Sep 25, 2026
11 checks passed
@jsonbailey
jsonbailey deleted the jb/sdk-3204/report-server-close branch September 25, 2026 20:30
jsonbailey pushed a commit that referenced this pull request Sep 28, 2026
🤖 I have created a release *beep* *boop*
---


##
[3.0.0](2.6.0...3.0.0)
(2026-09-28)


### ⚠ BREAKING CHANGES

* Report a server-initiated stream close to the error handler
([#91](#91))

### Features

* Report a server-initiated stream close to the error handler
([#91](#91))
([7e4dc1b](7e4dc1b))


### Bug Fixes

* Declare logger as a runtime dependency
([#94](#94))
([f7809c2](f7809c2))
* Stop the worker thread promptly when the client is closed during a
reconnect wait
([#93](#93))
([054b11b](054b11b))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Overview**
> **Release 3.0.0** — bumps the package version from `2.6.0` to `3.0.0`
in `.release-please-manifest.json`, `lib/ld-eventsource/version.rb`, and
documents the release in `CHANGELOG.md`.
> 
> This is a Release Please cut, not new library logic in the diff. The
changelog records what ships in **3.0.0**: a **breaking** behavior
change where a **server-initiated stream close** is reported through the
client **error handler** (e.g. `StreamClosedByServerError`), plus fixes
to declare **`logger` as a runtime dependency** and to **stop the worker
thread promptly** when the client is closed during a reconnect backoff
wait.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
d5431c5. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
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.

2 participants