FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

Signal STOP on the finishing multipart chunk, not an extra empty read by pavel-ptashyts · Pull Request #2232 · AsyncHttpClient/async-http-client · GitHub

Signal STOP on the finishing multipart chunk, not an extra empty read - #2232

Merged
hyperxpro merged 5 commits into
AsyncHttpClient:mainfrom
maygemdev:perf/multipart-stop-on-last-chunk
Jul 18, 2026
Merged

Signal STOP on the finishing multipart chunk, not an extra empty read#2232
hyperxpro merged 5 commits into
AsyncHttpClient:mainfrom
maygemdev:perf/multipart-stop-on-last-chunk

Conversation

Copy link
Copy Markdown
Contributor

MultipartBody.transferTo(ByteBuf) returned CONTINUE even on the call that wrote the last part and set done=true, so the terminal STOP was only discovered on the NEXT call — which allocated a fresh pooled buffer, found done==true, and returned STOP with an empty buffer. That extra readChunk/nextChunk cycle happened once per multipart request on the HTTPS / disabled-zero-copy path (BodyChunkedInput).

Return 'done ? STOP : CONTINUE' so the finishing call itself reports STOP. Both ByteBuf consumers send the bytes written on that call before honouring STOP — BodyChunkedInput returns the buffer and sets endOfInput (eliminating the extra empty readChunk); the HTTP/2 pump returns a readable buffer before checking state — so the terminal chunk is never dropped. The zero-copy (WritableByteChannel) and plain-HTTP FileRegion paths are unaffected.

Because STOP can now carry the body's last bytes, MultipartBodyTest's transferWithCopy helper (which exited on STOP without counting that call) is updated to count bytes on every call, mirroring the real consumers. Adds a test that the finishing call reports STOP and still carries all of the body's bytes; existing multipart body/part/upload tests pass unchanged. No public API change.

MultipartBody.transferTo(ByteBuf) returned CONTINUE even on the call that wrote the last part and set done=true, so the terminal STOP was only discovered on the NEXT call — which allocated a fresh pooled buffer, found done==true, and returned STOP with an empty buffer. That extra readChunk/nextChunk cycle happened once per multipart request on the HTTPS / disabled-zero-copy path (BodyChunkedInput).

Return 'done ? STOP : CONTINUE' so the finishing call itself reports STOP. Both ByteBuf consumers send the bytes written on that call before honouring STOP — BodyChunkedInput returns the buffer and sets endOfInput (eliminating the extra empty readChunk); the HTTP/2 pump returns a readable buffer before checking state — so the terminal chunk is never dropped. The zero-copy (WritableByteChannel) and plain-HTTP FileRegion paths are unaffected.

Because STOP can now carry the body's last bytes, MultipartBodyTest's transferWithCopy helper (which exited on STOP without counting that call) is updated to count bytes on every call, mirroring the real consumers. Adds a test that the finishing call reports STOP and still carries all of the body's bytes; existing multipart body/part/upload tests pass unchanged. No public API change.

Fixes finding AsyncHttpClient#9.
hyperxpro merged commit 664d418 into AsyncHttpClient:main Jul 18, 2026
13 checks passed
pavel-ptashyts deleted the perf/multipart-stop-on-last-chunk branch July 18, 2026 21:20
hyperxpro added a commit that referenced this pull request Jul 18, 2026
Motivation:

PR #2232 changed `MultipartBody.transferTo()` to return `STOP` on the
same call that writes the body's final bytes, meaning `STOP` may still
be accompanied by unread data in the target buffer. However,
`BodyState.STOP` is currently documented as meaning "nothing to read,"
and `AuthenticatorUtils`'s `auth-int` loop assumes this behavior, which
would truncate such a body (currently unreachable because multipart
bodies do not use this path).

Modification:

Update the `Body.transferTo()` and `BodyState.STOP` documentation to
clarify that `STOP` may accompany the final bytes and that consumers
must drain the target buffer before stopping. Add a comment in the
`auth-int` loop documenting its assumption.

Result:

The `STOP`-with-data contract is explicitly documented, and the existing
assumption in `AuthenticatorUtils` is clearly identified. Documentation
only; no behavioral changes.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
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


Back | FazBrowse Home | New Git URL