Skip to content

MLE-32953 Prevent retries of multipart streaming requests - #1979

Draft
rjdew-progress wants to merge 1 commit into
developfrom
MLE-32953
Draft

rjdew-progress wants to merge 1 commit into
developfrom
MLE-32953

Conversation

@rjdew-progress

Copy link
Copy Markdown
Contributor

Why

A Data Services request with streaming multipart input can fail with Stream closed after a preceding gzipped Row Manager response. The IOException retry interceptor sees only the outer MultipartBody, so it can retry the request even though a nested StreamingOutputImpl has already consumed and closed its source.

Approach

  • Mark StreamingOutputImpl as one-shot using OkHttp's native RequestBody.isOneShot() contract.
  • Make the IOException retry interceptor honor isOneShot() in addition to the Java Client's RetryableRequestBody contract.
  • Add a regression test proving that one-shot status propagates through MultipartBody and prevents a second request attempt.

Validation

  • ./gradlew marklogic-client-api:test --tests com.marklogic.client.impl.StreamingOutputImplTest
  • The complete core test task was also attempted; its server-dependent tests could not run because no deployed MarkLogic test instance was available on localhost:8012.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

Multipart bodies wrapping InputStreamHandle may still be replayed because one-shot status is not propagated through ObjectRequestBody.

Get a fresh assessment by requesting another Copilot review.

Review effort: Lite
Findings: 1 High severity

Open (1)
What changed in this PR

Prevents retries of multipart requests containing one-shot streaming bodies.

Changes:

  • Marks StreamingOutputImpl as one-shot.
  • Honors OkHttp’s isOneShot() contract in retry handling.
  • Adds multipart streaming regression coverage.
File Reviewed change
marklogic-client-api/​src/​test/​java/​com/​marklogic/​client/​impl/​StreamingOutputImplTest.java Tests one-shot multipart behavior.
marklogic-client-api/​src/​main/​java/​com/​marklogic/​client/​impl/​StreamingOutputImpl.java Declares streaming bodies as one-shot.
marklogic-client-api/​src/​main/​java/​com/​marklogic/​client/​impl/​okhttp/​RetryIOExceptionInterceptor.java Avoids retries for one-shot request bodies.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment on lines +46 to +47
if (requestBody != null && (requestBody.isOneShot() ||
requestBody instanceof RetryableRequestBody body && !body.isRetryable())) {
@rjdew-progress
rjdew-progress marked this pull request as draft September 23, 2026 20:34
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