Skip to content
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

gRPC convergence #508

Merged
merged 5 commits into from
Feb 23, 2022
Merged

gRPC convergence #508

merged 5 commits into from
Feb 23, 2022

Conversation

jskeet
Copy link
Collaborator

@jskeet jskeet commented Nov 1, 2021

This feels a little too easy to be "it", and there are some aspects we need to look more closely at:

  • Implementing the Grpc.Gcp side of things
  • Check the use of options for GrpcNetClient (lack of PrimaryUserAgent could be problematic)
  • Check the logic of GrpcAdapter.DefaultAdapter
  • Lots of testing in different scenarios
  • Consider GrpcNetClientAdapter integration with IHttpClientFactory and the like

However, this is a good starting point for discussion.

cc @jtattermusch

@jskeet jskeet added the do not merge Indicates a pull request not ready for merge, due to either quality or timing. label Nov 1, 2021
@jskeet jskeet requested a review from a team as a code owner November 1, 2021 14:47
@google-cla google-cla bot added the cla: yes This human has signed the Contributor License Agreement. label Nov 1, 2021
Copy link
Collaborator

@amanda-tarafa amanda-tarafa left a comment

Choose a reason for hiding this comment

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

Looks good overall.

{
private const string GrpcCoreAssemblyName = "Grpc.Core, Version=2.0.0.0, Culture=neutral, PublicKeyToken=d754f35622e28bad";

// Option names, copied from ChannelOptions
Copy link
Collaborator

Choose a reason for hiding this comment

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

It's a little weird that we have these harcoded here (ultimately a dependency). I don't mind at all tbh, it just jumped at me a little be.

I know it will be more reflection, but maybe use the Grpc.Core.ChannelOptions class with all the constants? That way, in the unlikely case those change, we don't have to change the code.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I'd prefer not to - to be honest, I think it's more likely that the names in the C# code will change e.g. in a new major version than that the underlying values will change, given that the whole ecosystem will depend on those.

// but in those environments, it's unlikely that Grpc.Core is being used anyway.
// The other methods can be invoked with delegates, but delegates can't refer directly to methods.

// TODO: Somehow cache the result of ConvertOptions? It's probably not called terribly frequently.
Copy link
Collaborator

Choose a reason for hiding this comment

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

  • Is ChannelOption inmutable?
  • Consider caching each individual option instead of the list? And you can pick and choose based on the value?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Yes, both ChannelOption and GrpcChanneloptions are immutable. Caching individual options would be trickier, given that we still need to come up with a sequence of the results. I suspect it's probably simpler to do all or nothing (and let's do nothing until we know we need to do anything...)

{
try
{
GrpcChannel.ForAddress("https://ignored.com");
Copy link
Collaborator

Choose a reason for hiding this comment

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

If this succeeds, can we guarantee that Grpc.Net.Client is fully usable?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

That's something we need to check with Jan. But I'm pretty sure we'll want some what of forcing it one way or another globally - an environment variable being the simplest approach.

…mmits

In reality we probably want to bring this code into Google.Api.Gax.Grpc, but that will be a later step.
…ient

The adapters will be reimplemented within Google.Api.Gax.Grpc in a later commit

(We could do it all in one commit, but this is at least simpler to follow.)
@jskeet jskeet force-pushed the grpc-convergence branch 2 times, most recently from 1fc26ad to ee95dc1 Compare February 23, 2022 11:46
@jskeet jskeet removed the do not merge Indicates a pull request not ready for merge, due to either quality or timing. label Feb 23, 2022
@jskeet
Copy link
Collaborator Author

jskeet commented Feb 23, 2022

This is now ready for real review with an eye to merging, but before I merge I'll create new issues for:

  • Considering whether clients should be able to set the default adapter (maybe only before first use?)
  • Adding an environment variable for forcing the use of one adapter or another
  • More options for GrpcNetClient, e.g. with an IHttpClientFactory and a logger.

@jskeet
Copy link
Collaborator Author

jskeet commented Feb 23, 2022

(I'll then probably try to get the Grpc.Gcp code in before addressing those issues.)

Copy link
Collaborator

@amanda-tarafa amanda-tarafa left a comment

Choose a reason for hiding this comment

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

LGTM

protected override ChannelBase CreateChannelImpl(string endpoint, ChannelCredentials credentials, GrpcChannelOptions options) =>
channelFactory.Value.Invoke(endpoint, credentials, options);

private static Func<string, ChannelCredentials, GrpcChannelOptions, ChannelBase> CreateFactory()
Copy link
Collaborator

Choose a reason for hiding this comment

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

tiny nit: CreateChannelFactory

And also, I think a comment here with something like "A function is created, instead of just having a factory method, to avoid the reflection bits/expression building every time."

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

SGTM.

We take a dependency on Grpc.Net.Client unconditionally, but no dependency on Grpc.Core. GrpcCoreAdapter loads dependencies via reflection (but in a way that is cheap after initial setup), allowing it to be used by applications that have a dependency - which could be conditional based on platform, for example.
Note that GrpcNetClientAdapter ignores the primary user agent option, so we can't easily test that the options are actually used.
This (lazily, and once) checks whether Grpc.Net.Client works - i.e. whether a channel can be constucted - and uses GrpcNetClientAdapter if so. Otherwise, it uses GrpcCoreAdapter. We may well want to tweak the details of this later.
@jskeet jskeet merged commit 8f89da8 into googleapis:main Feb 23, 2022
@jskeet jskeet deleted the grpc-convergence branch February 23, 2022 12:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
cla: yes This human has signed the Contributor License Agreement.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants