-
Notifications
You must be signed in to change notification settings - Fork 912
Bug fix for S3AsyncClient.putObject hangs if there is a connection reset while uploading of objects #3522
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
b157350
to
d276a97
Compare
…set while uploading of objects
d276a97
to
ffedaf7
Compare
SonarCloud Quality Gate failed. |
IOException err = new IOException(NettyUtils.closedChannelMessage(handlerCtx.channel())); | ||
runAndLogError(handlerCtx.channel(), () -> "Fail to execute SdkAsyncHttpResponseHandler#onError", | ||
() -> requestCtx.handler().onError(err)); | ||
executeFuture(handlerCtx).completeExceptionally(err); | ||
runAndLogError(handlerCtx.channel(), () -> "Could not release channel", () -> closeAndRelease(handlerCtx)); | ||
} else if (!Boolean.TRUE.equals(responseCompleted)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The logic is a bit confusing. Does it make sense to rearrange it with !Boolean.TRUE.equals(responseCompleted)
in an outer if clause and then just a simple if/else checking isLastByteWithout100Response
nested within?
if (!Boolean.TRUE.equals(responseCompleted)) {
if (!isLastByteWithout100Continue) {
IOException err = new IOException(NettyUtils.closedChannelMessage(handlerCtx.channel()));
runAndLogError(handlerCtx.channel(), () -> "Fail to execute SdkAsyncHttpResponseHandler#onError",
() -> requestCtx.handler().onError(err));
executeFuture(handlerCtx).completeExceptionally(err);
runAndLogError(handlerCtx.channel(), () -> "Could not release channel", () -> closeAndRelease(handlerCtx));
} else {
log.trace(handlerCtx.channel(),
() -> "Run error skipped because lastHttpContentReceived is "
+ handlerCtx.channel().attr(LAST_HTTP_CONTENT_RECEIVED_KEY).get() + " and 100ContinueMessage is "
+ handlerCtx.channel().attr(RESPONSE_100_CONTINUE_MESSAGE).get());
}
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
not required in new changes
@@ -463,18 +464,28 @@ public void cancel() { | |||
private void notifyIfResponseNotCompleted(ChannelHandlerContext handlerCtx) { | |||
RequestContext requestCtx = handlerCtx.channel().attr(REQUEST_CONTEXT_KEY).get(); | |||
Boolean responseCompleted = handlerCtx.channel().attr(RESPONSE_COMPLETE_KEY).get(); | |||
Boolean lastHttpContentReceived = handlerCtx.channel().attr(LAST_HTTP_CONTENT_RECEIVED_KEY).get(); | |||
boolean isLastByteWithout100Continue = isLastByteWithout100Response(handlerCtx); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a more explanatory name for this boolean? I think the channel key name is correct but here it'd be great if you'd know why a 100 continue disables the lastbyte check. isLastByteForResponseBody
? (not sure if this is 100% correct)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated with new PR to remove LastHttpContentHandler.
@@ -137,6 +160,20 @@ private Throwable captureException() { | |||
throw new AssertionError("Call did not fail as expected."); | |||
} | |||
|
|||
private Throwable captureExceptionWithHttpContinueResponse() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: Consider adding the future as a parameter to captureException
and keep it to one method
.responseHandler(new SdkAsyncHttpResponseHandler() { | ||
private SdkHttpResponse headers; | ||
|
||
@Override | ||
public void onHeaders(SdkHttpResponse headers) { | ||
this.headers = headers; | ||
} | ||
|
||
@Override | ||
public void onStream(Publisher<ByteBuffer> stream) { | ||
Flowable.fromPublisher(stream).forEach(b -> { | ||
}); | ||
} | ||
|
||
@Override | ||
public void onError(Throwable error) { | ||
} | ||
}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: Could be simplified by extracting the response handler
@@ -196,6 +197,7 @@ private void configureChannel() { | |||
channel.attr(REQUEST_CONTEXT_KEY).set(context); | |||
channel.attr(RESPONSE_COMPLETE_KEY).set(false); | |||
channel.attr(LAST_HTTP_CONTENT_RECEIVED_KEY).set(false); | |||
channel.attr(RESPONSE_100_CONTINUE_MESSAGE).set(false); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would it be possible to mark the completion of request in HttpStreamHandler
and get rid of LastHttpContentHandler? That way, we don't need to handle 100 continue message this classe
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Raised #3535 to change the logic where LAST_HTTP_CONTENT_RECEIVED_KEY is set
Closing since I have raised new PR #3535 |
…40713e5ab Pull request: release <- staging/cccb42d8-dd62-4d2f-8e1c-cc140713e5ab
Motivation and Context
Root Cause
HttpResponseStatus CONTINUE = newStatus(100, "Continue")
is received , which actually ignores the body, sends the lastByte and immediately starts reading the request stream.Modifications
Testing
Screenshots (if appropriate)
Types of changes
Checklist
mvn install
succeedsscripts/new-change
script and following the instructions. Commit the new file created by the script in.changes/next-release
with your changes.License