Skip to content

fix(http): close cancelled Java streams and preserve backpressure - #2285

Open
kyboi wants to merge 2 commits into
JetBrains:developfrom
Kreoh:contribute/java-sse-lifetime
Open

kyboi wants to merge 2 commits into
JetBrains:developfrom
Kreoh:contribute/java-sse-lifetime

Conversation

@kyboi

@kyboi kyboi commented Sep 30, 2026

Copy link
Copy Markdown

Closes #2280. Includes #2284, which fixes #2279.

Java SSE collectors can remain blocked while awaiting headers or an idle response body. Both Java streaming flows can lose chunks when their channels fill, and lines can stall cancellation while awaiting body data.

Share response ownership through a private helper: run blocking requests interruptibly on the IO dispatcher, close the body exactly once on completion, failure or cancellation, and deliver chunks with suspending send. Preserve pending body ownership when cancellation races with response arrival. Callback cancellation reaches the collector, decoder failure stops further processing, and closing a cancelled body cannot replace cancellation with an I/O error. Retain lines' declared response charset and blank-line behaviour.

This SSE lifetime fix is already included in Kroog and is working in production applications using Kroog. Original implementations by mrkim: d5ca5f6b2 and 1f64cf724. This patch adapts the SSE implementation into a shared helper and extends equivalent handling to lines. The lines extension and cancellation-race guard have local regression evidence; they are additional changes beyond the deployed Kroog SSE source.

The JDK body lifecycle contract and coroutine send contract establish the expected resource ownership and delivery behaviour.

Twenty focused tests cover local HTTP servers, controlled response arrival, body closure, cancellation, failure, lossless delivery, bounded decoding and declared charset handling. Baseline red runs demonstrate sixteen failing regression cases and three passing compatibility controls; the charset control is additional validation.

This branch is stacked on the separately reviewed SSE framing commit 62fd7298b54d7aa883564b4845c407625e6f1e7b. It can merge with that ancestor intact, or merge #2284 first and rebase the transport change onto develop. The transport diff adds no public symbols or dependencies. No non-JVM targets are involved.

Validation: all 61 module JVM tests pass, including the twenty added tests and seven framing tests. Module ktlintCheck, jar and generatePomFileForMavenPublication pass. The compiled JVM ABI exactly matches the checked-in dump. Target: develop.

This branch has not been deployed

No deployments
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.

Java streaming flows can stall cancellation and drop chunks Java HTTP client decodes individual SSE lines instead of complete data events

1 participant