-
Notifications
You must be signed in to change notification settings - Fork 5.3k
http: add onComplete to AsyncClient::StreamCallbacks #7752
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
Merged
Merged
Changes from all commits
Commits
Show all changes
16 commits
Select commit
Hold shift + click to select a range
42326d2
http: add onClosure to AsyncClient::StreamCallbacks
goaway d92830d
update tests
goaway c5d44bd
fix typo
goaway 69013ef
update AsyncRequest
goaway 7d8a7b6
update Grpc::AsyncClient
goaway 2c82fa1
fix unused parameter
goaway 39132b9
fix format
goaway 7a632bc
fix a couple tests
goaway e6efa99
revert AsyncRequestImpl change
goaway 5962e37
fix another test
goaway 4db6153
first modification
8187ae4
update
4181ae1
guard closeLocal and closeRemote
goaway 40031d5
cleanup
goaway ef543d8
additional clarification comment
goaway 16af15b
add detail to comments and TODOs
goaway File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
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
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
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
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -142,17 +142,48 @@ void AsyncStreamImpl::sendTrailers(HeaderMap& trailers) { | |
| } | ||
|
|
||
| void AsyncStreamImpl::closeLocal(bool end_stream) { | ||
| // TODO(goaway): This assert maybe merits reconsideration. It seems to be saying that we shouldn't | ||
|
Member
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. |
||
| // get here when trying to send the final frame of a stream that has already been closed locally, | ||
| // but it's fine for us to get here if we're trying to send a non-final frame. There's not an | ||
| // obvious reason why the first case would be not okay but the second case okay. | ||
| ASSERT(!(local_closed_ && end_stream)); | ||
| // This guard ensures that we don't attempt to clean up a stream or fire a completion callback | ||
| // for a stream that has already been closed. Both send* calls and resets can result in stream | ||
| // closure, and this state may be updated synchronously during stream interaction and callbacks. | ||
| // Additionally AsyncRequestImpl maintains behavior wherein its onComplete callback will fire | ||
| // immediately upon receiving a complete response, regardless of whether it has finished sending | ||
| // a request. | ||
| // Previous logic treated post-closure entry here as more-or-less benign (providing later-stage | ||
| // guards against redundant cleanup), but to surface consistent stream state via callbacks, | ||
| // it's necessary to be more rigorous. | ||
| // TODO(goaway): Consider deeper cleanup of assumptions here. | ||
| if (local_closed_) { | ||
| return; | ||
| } | ||
|
|
||
| local_closed_ |= end_stream; | ||
| local_closed_ = end_stream; | ||
| if (complete()) { | ||
| stream_callbacks_.onComplete(); | ||
| cleanup(); | ||
| } | ||
| } | ||
|
|
||
| void AsyncStreamImpl::closeRemote(bool end_stream) { | ||
| remote_closed_ |= end_stream; | ||
| // This guard ensures that we don't attempt to clean up a stream or fire a completion callback for | ||
| // a stream that has already been closed. This function is called synchronously after callbacks | ||
| // have executed, and it's possible for callbacks to, for instance, directly reset a stream or | ||
| // close the remote manually. The test case ResetInOnHeaders covers this case specifically. | ||
| // Previous logic treated post-closure entry here as more-or-less benign (providing later-stage | ||
| // guards against redundant cleanup), but to surface consistent stream state via callbacks, it's | ||
| // necessary to be more rigorous. | ||
| // TODO(goaway): Consider deeper cleanup of assumptions here. | ||
| if (remote_closed_) { | ||
| return; | ||
| } | ||
|
|
||
| remote_closed_ = end_stream; | ||
| if (complete()) { | ||
| stream_callbacks_.onComplete(); | ||
| cleanup(); | ||
| } | ||
| } | ||
|
|
@@ -184,36 +215,42 @@ AsyncRequestImpl::AsyncRequestImpl(MessagePtr&& request, AsyncClientImpl& parent | |
|
|
||
| void AsyncRequestImpl::initialize() { | ||
| sendHeaders(request_->headers(), !request_->body()); | ||
| if (!remoteClosed() && request_->body()) { | ||
| sendData(*request_->body(), true); | ||
| // AsyncRequestImpl has historically been implemented to fire onComplete immediately upon | ||
| // receiving a complete response, regardless of whether the underlying stream was fully closed (in | ||
| // other words, regardless of whether the complete request had been sent). This had the potential | ||
| // to leak half-closed streams, which is now covered by manually firing closeLocal below. (See | ||
| // test PoolFailureWithBody for an example execution path.) | ||
| // TODO(goaway): Consider deeper cleanup of assumptions here. | ||
| if (request_->body()) { | ||
| // sendHeaders can result in synchronous stream closure in certain cases (e.g. connection pool | ||
mattklein123 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| // failure). | ||
| if (remoteClosed()) { | ||
| // In the case that we had a locally-generated response, we manually close the stream locally | ||
| // to fire the completion callback. This is a no-op if we had a locally-generated reset | ||
| // instead. | ||
| closeLocal(true); | ||
| } else { | ||
| sendData(*request_->body(), true); | ||
| } | ||
| } | ||
| // TODO(mattklein123): Support request trailers. | ||
| } | ||
|
|
||
| void AsyncRequestImpl::onComplete() { callbacks_.onSuccess(std::move(response_)); } | ||
|
|
||
| void AsyncRequestImpl::onHeaders(HeaderMapPtr&& headers, bool end_stream) { | ||
| void AsyncRequestImpl::onHeaders(HeaderMapPtr&& headers, bool) { | ||
| response_ = std::make_unique<ResponseMessageImpl>(std::move(headers)); | ||
|
|
||
| if (end_stream) { | ||
| onComplete(); | ||
| } | ||
| } | ||
|
|
||
| void AsyncRequestImpl::onData(Buffer::Instance& data, bool end_stream) { | ||
| void AsyncRequestImpl::onData(Buffer::Instance& data, bool) { | ||
| if (!response_->body()) { | ||
| response_->body() = std::make_unique<Buffer::OwnedImpl>(); | ||
| } | ||
| response_->body()->move(data); | ||
|
|
||
| if (end_stream) { | ||
| onComplete(); | ||
| } | ||
| } | ||
|
|
||
| void AsyncRequestImpl::onTrailers(HeaderMapPtr&& trailers) { | ||
| response_->trailers(std::move(trailers)); | ||
| onComplete(); | ||
| } | ||
|
|
||
| void AsyncRequestImpl::onReset() { | ||
|
|
||
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
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
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
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.