-
Notifications
You must be signed in to change notification settings - Fork 923
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
ClientRequestContext#cancel
cancels the associated request immediately
#5800
Changes from 2 commits
3b8958a
59aa40a
e6f95c1
7289baf
06012a1
88c4c18
5cb756b
9068e4f
36c094c
610f83d
cc8db83
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -428,7 +428,8 @@ private void updateFlags(int flags) { | |||||||||||||||
private static void completeSatisfiedFutures(RequestLogFuture[] satisfiedFutures, RequestLog log, | ||||||||||||||||
RequestContext ctx) { | ||||||||||||||||
if (!ctx.eventLoop().inEventLoop()) { | ||||||||||||||||
ctx.eventLoop().execute(() -> completeSatisfiedFutures(satisfiedFutures, log, ctx)); | ||||||||||||||||
ctx.eventLoop().withoutContext().execute( | ||||||||||||||||
() -> completeSatisfiedFutures(satisfiedFutures, log, ctx)); | ||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Q) Why was the context removed? Shouldn't the request context be propagated to the callbacks of There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It seemed like we were making an effort to clear the request context when completing logs. e.g. armeria/core/src/main/java/com/linecorp/armeria/client/HttpClientDelegate.java Lines 242 to 247 in 72ebfe1
I saw There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It was an inevitable choice Netty can handle pending messages in batch mode that can cause a request context leak. If an action does not perform sequentially in the callbacks of Netty operations, I think a context-aware executor is generally preferred. I am not strong here. If you have any other workarounds, it is okay to keep it. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
I see, I think I misunderstood the intention then. My original guess was that if request logs for multiple requests are waited on a single condition, users would easily see a request context leak. I'm not sure I understood what you mean by batch mode though. I thought channels are tied to a single thread, and within a single thread as long as the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Context leaks could happen even with Say we have a simple service that adds a callback to try (ctx.push()) {
val response = HttpResponse.streaming();
response.write(...);
response.whenComplete().thenAccept(unused -> {
// Do something else.
})
}
However, it would be impossible to leak the context with
As you said, contexts are not propagated in some cases. I agree with keeping the current style in terms of consistency. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thanks for the explanation 👍
I understood that even if ClientRequestContext ctx1 = null;
ClientRequestContext ctx2 = null;
// represents a single task
CommonPools.workerGroup().execute(() -> {
// request 1
try (SafeCloseable sf = ctx1.push()) {
ctx1.logBuilder().endResponse();
}
// request 2
try (SafeCloseable sf = ctx2.push()) {
ctx2.logBuilder().endResponse();
}
});
👍 for me as well. Ultimately, my thought was that it depends more on how users are using the API - for this reason it is probably more important that the context is pushed (or not) consistently. e.g. I can imagine the following scenario HttpResponseWriter res1 = null;
HttpResponseWriter res2 = null;
CompletableFuture.allOf(ctx1.log().whenComplete(), ctx2.log().whenComplete())
.handle((v, t) -> {
res1.close();
res2.close();
// when the res is completed, the same thread may call ctx.push somewhere
return null;
}); There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sorry for chiming in late. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I didn't expect this change to be so controversial 😅 Let me just revert this change since this isn't really critical to this PR |
||||||||||||||||
return; | ||||||||||||||||
} | ||||||||||||||||
for (RequestLogFuture f : satisfiedFutures) { | ||||||||||||||||
|
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.
I suggested removing
updateTask()
method, but that would result in too many changes to the existing code. As long as the implemetation is correct, I'm okay to maintain the current style and focus on implementing the response timeout mode.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.
For the record,
updateTask()
doesn't necessarily have to be removed - it can still be used internally since the oldCancellationScheduler#start
acted similarly toupdateTask()
.It is probably more important to unify and simplify the request/response abortion mechanism. This seems difficult to do at the moment for client-side. In particular, when one attempts this one should take note of 1) consistency between
[req|res].cause
andlog.[req|res]Cause
, 2) setting the correct exception type (e.g.UnprocessedRequestException
).