Skip to content

Remove grpc_httpcli_context#27867

Merged
apolcyn merged 7 commits intogrpc:masterfrom
apolcyn:remove_http_context
Jan 11, 2022
Merged

Remove grpc_httpcli_context#27867
apolcyn merged 7 commits intogrpc:masterfrom
apolcyn:remove_http_context

Conversation

@apolcyn
Copy link
Copy Markdown
Contributor

@apolcyn apolcyn commented Oct 29, 2021

grpc_httpcli_context currently has just a grpc_pollset_set field, which seems to only be necessary in order to wrap the grpc_httpcli_{get,post} pollent parameter in the case that pollent is a grpc_pollset. We can remove the need for callers to manage this and manage it within the requests themselves.

Motivation: I'm trying to add cancellation support to grpc_httpcli_{get,post}. My first idea was to leverage grpc_httpcli_context to do the cancellation with something along the lines of grpc_httpcli_cancel(context), but that doesn't work out well because grpc_httpcli_context can be used across multiple requests. So we'd need to instead return something from grpc_httpcli_{get,post} which tracks the request and can do cancellation, but it seems odd for something like that to co-exist with grpc_httpcli_context.

@apolcyn apolcyn added lang/core release notes: yes Indicates if PR needs to be in release notes labels Oct 29, 2021
@apolcyn apolcyn requested a review from ctiller October 29, 2021 17:48
@apolcyn apolcyn marked this pull request as ready for review October 29, 2021 17:48
@apolcyn apolcyn requested a review from markdroth as a code owner October 29, 2021 17:48
@markdroth
Copy link
Copy Markdown
Member

I'd like @ctiller to weigh in on this to confirm my understanding and reasoning here. However, I'm not sure that this PR is the right approach, for two reasons.

First, I believe that the reason grpc_httpcli_context exists and contains a grpc_pollset_set is that we want multiple gRPC calls to be able to poll the same HTTP request. For example, in a case like oauth creds, the first gRPC call might trigger an HTTP request to get the oauth token, but then a second call might be started that is also blocked on waiting for the oauth token, and then the first request might be cancelled before the HTTP request completes. In that case, we need the CQ polling for the second request to be able to make forward progress on the HTTP request. But if the two calls are on different CQs and we don't combine their pollsets, then nothing will be doing polling on the HTTP request, and it will never make forward progress. (To be fair, this is a short-term problem, since all of the pollset stuff will go away when we migrate to EventEngine, but I think we still need it until then.)

Second, even if grpc_httpcli_context weren't needed for polling reasons, it's not clear to me why we need to get rid of it in order to add cancellation. I think the right way to think about the structure here is that grpc_httpcli_context is analogous to a channel and grpc_httpcli_request is analogous to an RPC call. The existence of the channel in the API does not prevent us from cancelling a call, so I don't see why the presence of grpc_httpcli_context should prevent us from cancelling an individual grpc_httpcli_request. The cancellation should be an operation on grpc_httpcli_request, and the semantics of that operation shouldn't be affected by the presence of grpc_httpcli_context.

@apolcyn
Copy link
Copy Markdown
Contributor Author

apolcyn commented Dec 15, 2021

First, I believe that the reason grpc_httpcli_context exists and contains a grpc_pollset_set is that we want multiple gRPC calls to be able to poll the same HTTP request. For example, in a case like oauth creds, the first gRPC call might trigger an HTTP request to get the oauth token, but then a second call might be started that is also blocked on waiting for the oauth token, and then the first request might be cancelled before the HTTP request completes. In that case, we need the CQ polling for the second request to be able to make forward progress on the HTTP request. But if the two calls are on different CQs and we don't combine their pollsets, then nothing will be doing polling on the HTTP request, and it will never make forward progress. (To be fair, this is a short-term problem, since all of the pollset stuff will go away when we migrate to EventEngine, but I think we still need it until then.)

Right, I also initially thought that this polling problem necessitated the shared context object, but it looks like all callers are actually already solving this problem by merging interested parties into grpc_httpcli_{get,post}'s pollent parameter themselves. I.e., the grpc_httpcli_context is object is still redundant.

Here's my audit of all non-test usages of grpc_httpcli_{get,post} in the codebase:

  1. Multiple usages of grpc_httpcli_{get,post} within oauth2_credentials.cc, example: interested parties have already been merged into the pollent parameter in the parent class's get_request_metadata.

  2. In google_default_credentials: there is only one interested party which is the local method.

  3. Multiple usages of grpc_httpcli_{get,post} in child classes of ExternalAccountCredentials: the pollent parameter is passed down from ExternalAccountCredentials::fetch_oauth2 method, and that pollent parameter has already merged all interested in parties in get_request_metadata

I also see one usage of grpc_httpcli_get internally, but that is a synchronous usage and there is no shared pollset set there.

Second, even if grpc_httpcli_context weren't needed for polling reasons, it's not clear to me why we need to get rid of it in order to add cancellation. I think the right way to think about the structure here is that grpc_httpcli_context is analogous to a channel and grpc_httpcli_request is analogous to an RPC call. The existence of the channel in the API does not prevent us from cancelling a call, so I don't see why the presence of grpc_httpcli_context should prevent us from cancelling an individual grpc_httpcli_request. The cancellation should be an operation on grpc_httpcli_request, and the semantics of that operation shouldn't be affected by the presence of grpc_httpcli_context.

Indeed the presence of the grpc_httpcli_context object doesn't prevent us from adding cancellation, but I do think it makes the API more cumbersome than it needs to be. So I just figured we might as well delete it as a part of the API changes to add cancellation.

@apolcyn
Copy link
Copy Markdown
Contributor Author

apolcyn commented Dec 15, 2021

Note, there is also one more usage of grpc_httpcli_get in the google c2p resolver.

But again, the pollent parameter in use there is the resolver's pollset set, and interested parties must have already been merged into that, otherwise the polling problem referred to would exist for resolvers on all other I/O.

@apolcyn apolcyn assigned ctiller and unassigned markdroth Dec 16, 2021
@ctiller
Copy link
Copy Markdown
Member

ctiller commented Dec 29, 2021

Mark's right on the original intent (to share polling context between requests), and I think Alex is right on the current status (we just don't actually)... and that status is going to become unchangeable soon as we remove pollset_set anyway. I also agree with Alex on the thinking that we'll want to return some handle to cancel with from get/post. I also agree with Mark on the reasoning that it needn't be awkward.

That said, we're asking clients to carry state that we don't use, and I think enough time has passed since I wrote this thing that we can safely say that we probably won't add another use for it in the near term, so I think my vote lands on let's delete the thing and simplify calling code.

Copy link
Copy Markdown
Member

@markdroth markdroth left a comment

Choose a reason for hiding this comment

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

Okay, if we're already handling the pollset merging a different way, then I'm fine with this.

Craig, thanks for the sanity-check!

@apolcyn
Copy link
Copy Markdown
Contributor Author

apolcyn commented Jan 11, 2022

artifact and distrib linux tests are known issue: #28483

basic tests objc ios looks like #23933

@apolcyn apolcyn merged commit 066a50b into grpc:master Jan 11, 2022
@copybara-service copybara-service Bot added the imported Specifies if the PR has been imported to the internal repository label Jan 13, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bloat/none disposition/Needs Internal Changes imported Specifies if the PR has been imported to the internal repository lang/core perf-change/none release notes: yes Indicates if PR needs to be in release notes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants