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

Add C# LiteClientBase and "lite_client" codegen option #18705

Merged
merged 7 commits into from Jun 3, 2019

Conversation

jtattermusch
Copy link
Contributor

Based on #18532

To allow creating client stubs while only depending on Grpc.Core.Api (= the managed code).
To make this useable, we would also need to add experimental codegen option to generate the lite stubs in codegen.

Some more context in the doc grpc/grpc-dotnet#180. Note that we haven't figured out many questions around the client-side API (and how to expose the concept of a "client channel", along with all its functionality), so the solution with "LiteClientBase" might be temporary.

@jtattermusch
Copy link
Contributor Author

CC @apolcyn @JamesNK @JunTaoLuo

/// is provided by decorating the call invoker.
/// Note: experimental API that can change or be removed without any prior notice.
/// </summary>
public abstract class LiteClientBase
Copy link
Contributor Author

Choose a reason for hiding this comment

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

the name of the class is TBD.

Copy link
Member

Choose a reason for hiding this comment

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

CoreClientBase? NetCoreClientBase? ManagedClientBase?

Choose a reason for hiding this comment

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

Since the alternative also runs on .NET Core. I prefer ManagedClientbase as suggested in https://github.com/grpc/grpc-dotnet/pull/180/files.

@jtattermusch
Copy link
Contributor Author

@JamesNK @JunTaoLuo I haven't quite figured out the name of the protoc plugin option yet, but the LiteClientBase and protoc plugin changes are mostly done. Worth taking an initial look.

@jtattermusch jtattermusch added lang/C# release notes: yes Indicates if PR needs to be in release notes labels Apr 29, 2019
/// <summary>
/// Call invoker that throws <c>NotImplementedException</c> for all requests.
/// </summary>
private class UnimplementedCallInvoker : CallInvoker

Choose a reason for hiding this comment

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

Maybe we can move UnimplementedCallInvoker from Grpc.Core to Grpc.Core.Api and reuse it here instead of creating a private class?

Copy link
Member

Choose a reason for hiding this comment

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

It would then need to be public or internal (there is an internals visible to attribute that gives access to Grpc.Core). I don't think either is worth the hassle compared to some copy and paste.

@JunTaoLuo
Copy link

JunTaoLuo commented May 1, 2019

Edit: we spoke about this offline and I'm okay with ClientBase and LiteClientBase side by side. However, I think the default should only generate ClientBase so there's no change from previous behaviour. We can independently opt in to LiteClientBase or opt out of ClientBase with options.

It looks like by default, both a ClientBase and a LiteClientBase will be generated. I'm not sure if that's the best option since current client projects will be bloated after upgrading. The fact that no one should ever need to have both ClientBase and LiteClientBase side by side, I would modify the logic so only one of them is generated, not both.

For example, add a --use-lite-client option which defaults to false. This will be an option that's orthogonal to --no-client:

Options --no-client no --no-client
no --use-lite-client do not generate client generate using ClientBase
--use-lite-client do not generate client, advise --use-lite-client will be ignored when --no-client is set generate using LiteClientBase

/// is provided by decorating the call invoker.
/// Note: experimental API that can change or be removed without any prior notice.
/// </summary>
public abstract class LiteClientBase
Copy link
Member

Choose a reason for hiding this comment

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

CoreClientBase? NetCoreClientBase? ManagedClientBase?

src/csharp/Grpc.Core.Api/LiteClientBase.cs Outdated Show resolved Hide resolved
/// <summary>
/// Call invoker that throws <c>NotImplementedException</c> for all requests.
/// </summary>
private class UnimplementedCallInvoker : CallInvoker
Copy link
Member

Choose a reason for hiding this comment

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

It would then need to be public or internal (there is an internals visible to attribute that gives access to Grpc.Core). I don't think either is worth the hassle compared to some copy and paste.

@jtattermusch jtattermusch changed the title WIP: Add C# LiteClientBase Add C# LiteClientBase and "lite_client" codegen option May 29, 2019
@jtattermusch
Copy link
Contributor Author

After some delay, I think this is now ready for final review. Here are some modifications I made:

  • I added lite_client plugin options (false by default). If true, a client that inherits from LiteClientBase will be generated.
  • There is no way to generate both "lite" and "full" client at the same time. I gave that a bit more thought and it seemed that would only create confusion (especially around needing to use different client class names when both "full" and "lite" would be both).

Usage scenarios:

  • Using Grpc.Core only: just use the client generated by default (lite_client=false) and everything will work as always.
  • Using Grpc.Core and grpc-dotnet in the same application: generate the full client (lite_client=false). All the dependencies will be fine because we're referencing Grpc.Core and the clients will be fully usable with grpc-dotnet (use constructor that takes a CallInvoker).
  • Using grpc-dotnet only (managed scenario): set lite_client=true and there will be no dependencies on Grpc.Core (only Grpc.Core.Api).

@jtattermusch
Copy link
Contributor Author

@apolcyn @JunTaoLuo @JamesNK PTAL.

@JamesNK
Copy link
Member

JamesNK commented May 29, 2019

I added lite_client plugin options (false by default)

Who sets the option?

Have you thought about the name anymore? re: #18705 (comment)

Copy link
Contributor

@apolcyn apolcyn left a comment

Choose a reason for hiding this comment

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

general comment: can we generate lite_client protos on one of the examples or tests? it may help for comparing diffs later

out->Print("public partial class $name$ : grpc::ClientBase<$name$>\n",
"name", GetClientClassName(service));
} else {
out->Print("/// <summary>Lite client for $servicename$</summary>\n",
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: it may help to add a "experimental API" comment to this generated doc

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I added a version of math.proto that uses the lite_client option and I checked in the generated code.

Copy link
Contributor

@apolcyn apolcyn left a comment

Choose a reason for hiding this comment

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

LGTM with two nits. In particular I'd prefer to check in new generated stubs from lite_client mode here

Copy link

@JunTaoLuo JunTaoLuo left a comment

Choose a reason for hiding this comment

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

@JamesNK We would most likely set the --lite_client option in a build target in Grpc.AspNetCore.Server.

@JamesNK
Copy link
Member

JamesNK commented May 30, 2019

We would most likely set the --lite_client option in a build target in Grpc.AspNetCore.Server.

I'm not super familiar with how the proto generator works.

So would Grpc.AspNetCore.Server set some value to say the lite client should be used and then Grpc.Tools would use that value to decide whether to include --lite_client when it invokes the proto generator?

@jtattermusch
Copy link
Contributor Author

We would most likely set the --lite_client option in a build target in Grpc.AspNetCore.Server.

I'm not super familiar with how the proto generator works.

So would Grpc.AspNetCore.Server set some value to say the lite client should be used and then Grpc.Tools would use that value to decide whether to include --lite_client when it invokes the proto generator?

Yes, except to be precise, the option is not passed to the plugin as --lite_client but in a slightly different form, that is based on how options are passed to protoc plugins (they can be added as prefix to --grpc_out or separately under --grpc_opt): https://github.com/protocolbuffers/protobuf/blob/fa5a69e73b0dd667ff15062adbc170310d440ee9/src/google/protobuf/compiler/command_line_interface.h#L174

@jtattermusch
Copy link
Contributor Author

Known failures:
#18416
#18967
#19005

@jtattermusch jtattermusch merged commit be9cb5e into grpc:master Jun 3, 2019
@lock lock bot locked as resolved and limited conversation to collaborators Sep 1, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
lang/C# 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.

None yet

4 participants