Skip to content

fix: Open a new connection on each stream reconnect - #232

Merged
kinyoklion merged 2 commits into
mainfrom
rlamb/stream-connection-pool-reuse
Oct 13, 2026
Merged

kinyoklion merged 2 commits into
mainfrom
rlamb/stream-connection-pool-reuse

Conversation

@kinyoklion

@kinyoklion kinyoklion commented Oct 9, 2026 •

Copy link
Copy Markdown
Member

Summary

After a stream read timeout on an HTTP/2 connection, OkHttp keeps the connection in the pool and treats it as healthy until a 1 second ping deadline passes. After a long-lived stream fails, the first reconnect comes 0.5 to 1 second later. So when the network silently drops the stream connection, the reconnect opens a new stream on the same dead connection and waits for another 5 minute read timeout. Recovery takes about 10 minutes instead of 5.

The stream's OkHttp client now uses a connection pool that keeps no idle connections, so each reconnect opens a new connection. This applies to the FDv1 streaming data source and the FDv2 streaming synchronizer. The stream client has its own pool, so polling and event delivery are unchanged.

This also updates okhttp-eventsource to 5.0.1, which closes the response body when a stream stops (launchdarkly/okhttp-eventsource#114). Without that, a restart that the SDK starts itself, such as after an FDv2 goodbye or invalid data, leaves the abandoned HTTP/2 call holding the old connection, so this pool setting cannot close it.

New tests count TCP connections across a reconnect and fail without this change.


Note

Overview
Fixes slow recovery when an SSE stream dies on HTTP/2 by forcing each stream reconnect to use a fresh TCP connection instead of reusing a pooled connection OkHttp may still treat as healthy for ~1s after a read timeout.

StreamProcessor (FDv1) and StreamingSynchronizerImpl (FDv2) now configure the eventsource OkHttp client with ConnectionPool(0, 1, SECONDS) after httpProperties applies its default pool, so idle connections are not kept for streaming only. Polling and other HTTP clients are unchanged.

Bumps okhttp-eventsource to 5.0.1 (pairs with upstream fix for abandoned HTTP/2 calls on SDK-initiated restarts). Adds integration tests that count TCP connections across a reconnect and expect two connections.

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

After a stream read timeout on an HTTP/2 connection, OkHttp keeps the
connection pooled and treats it as healthy until a 1 second ping deadline
passes. The first reconnect after a long-lived stream comes 0.5 to 1 second
later, so it reuses the dead connection and waits for another read timeout.

The stream client now uses a connection pool that keeps no idle connections,
for both the FDv1 streaming data source and the FDv2 streaming synchronizer.
@kinyoklion
kinyoklion marked this pull request as ready for review October 12, 2026 17:20
@kinyoklion
kinyoklion requested a review from a team as a code owner October 12, 2026 17:20
@kinyoklion

Copy link
Copy Markdown
Member Author

I'll hold the release of this one until the updated event source is included as well.

5.0.1 closes the response body when a stream stops. A restart that the SDK
starts itself then releases the HTTP/2 connection, so the stream connection
pool can close it.
@kinyoklion
kinyoklion merged commit 770f0a9 into main Oct 13, 2026
25 checks passed
@kinyoklion
kinyoklion deleted the rlamb/stream-connection-pool-reuse branch October 13, 2026 21:04
kinyoklion pushed a commit that referenced this pull request Oct 14, 2026
🤖 I have created a release *beep* *boop*
---


##
[7.17.3](launchdarkly-java-server-sdk-7.17.2...launchdarkly-java-server-sdk-7.17.3)
(2026-10-14)


### Bug Fixes

* Open a new connection on each stream reconnect
([#232](#232))
([770f0a9](770f0a9))
* Reconnect the FDv2 stream after a restart that follows an earlier
disconnect
([#233](#233))
([3c69b44](3c69b44))

---
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 7.17.3** for `lib/sdk/server`: bumps the published SDK
version everywhere Release Please tracks
(`.release-please-manifest.json`, `gradle.properties`, and
`Version.SDK_VERSION`) from **7.17.2** to **7.17.3**.
> 
> The new **CHANGELOG** entry documents two **bug fixes** already landed
on main: opening a **fresh connection on each stream reconnect**, and
ensuring the **FDv2 stream reconnects** after a restart that follows an
earlier disconnect. This PR does not contain those code changes—only the
version and release notes.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
6938932. 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