From ad51f572fd270f2323e3aa2c1d2775cab9087af2 Mon Sep 17 00:00:00 2001 From: Doug Fawley Date: Thu, 4 Jun 2020 10:56:13 -0700 Subject: [PATCH] protoc-gen-go-grpc: add requirement of embedding UnimplementedServer in services (#3657) --- .../grpc_lb_v1/load_balancer_grpc.pb.go | 4 +++- balancer/grpclb/grpclb_test.go | 1 + .../proto/grpc_lookup_v1/rls_grpc.pb.go | 4 +++- .../testutils/fakeserver/fakeserver.go | 1 + benchmark/benchmark.go | 2 ++ benchmark/grpc_testing/services_grpc.pb.go | 8 +++++-- benchmark/worker/main.go | 1 + channelz/grpc_channelz_v1/channelz_grpc.pb.go | 4 +++- channelz/service/service.go | 4 +++- cmd/protoc-gen-go-grpc/README.md | 21 +++++++++++++++++++ cmd/protoc-gen-go-grpc/grpc.go | 15 ++++++++++++- cmd/protoc-gen-go-grpc/main.go | 11 +++++++++- .../proto/grpc_gcp/handshaker_grpc.pb.go | 4 +++- examples/features/proto/echo/echo_grpc.pb.go | 4 +++- .../helloworld/helloworld_grpc.pb.go | 4 +++- .../routeguide/route_guide_grpc.pb.go | 4 +++- health/grpc_health_v1/health_grpc.pb.go | 4 +++- health/server.go | 1 + interop/fake_grpclb/fake_grpclb.go | 1 + interop/grpc_testing/test_grpc.pb.go | 12 ++++++++--- interop/test_utils.go | 1 + interop/xds/client/client.go | 4 +++- profiling/proto/service_grpc.pb.go | 4 +++- profiling/service/service.go | 1 + .../reflection_grpc.pb.go | 4 +++- reflection/grpc_testing/test_grpc.pb.go | 4 +++- reflection/serverreflection.go | 1 + regenerate.sh | 2 +- stats/grpc_testing/test_grpc.pb.go | 4 +++- stress/client/main.go | 1 + stress/grpc_testing/metrics_grpc.pb.go | 4 +++- test/grpc_testing/test_grpc.pb.go | 4 +++- 32 files changed, 120 insertions(+), 24 deletions(-) create mode 100644 cmd/protoc-gen-go-grpc/README.md diff --git a/balancer/grpclb/grpc_lb_v1/load_balancer_grpc.pb.go b/balancer/grpclb/grpc_lb_v1/load_balancer_grpc.pb.go index 40cbf5724..5a3a2ec57 100644 --- a/balancer/grpclb/grpc_lb_v1/load_balancer_grpc.pb.go +++ b/balancer/grpclb/grpc_lb_v1/load_balancer_grpc.pb.go @@ -61,12 +61,14 @@ func (x *loadBalancerBalanceLoadClient) Recv() (*LoadBalanceResponse, error) { } // LoadBalancerServer is the server API for LoadBalancer service. +// All implementations should embed UnimplementedLoadBalancerServer +// for forward compatibility type LoadBalancerServer interface { // Bidirectional rpc to get a list of servers. BalanceLoad(LoadBalancer_BalanceLoadServer) error } -// UnimplementedLoadBalancerServer can be embedded to have forward compatible implementations. +// UnimplementedLoadBalancerServer should be embedded to have forward compatible implementations. type UnimplementedLoadBalancerServer struct { } diff --git a/balancer/grpclb/grpclb_test.go b/balancer/grpclb/grpclb_test.go index d701b6d21..45d2df645 100644 --- a/balancer/grpclb/grpclb_test.go +++ b/balancer/grpclb/grpclb_test.go @@ -187,6 +187,7 @@ func (s *rpcStats) String() string { } type remoteBalancer struct { + lbgrpc.UnimplementedLoadBalancerServer sls chan *lbpb.ServerList statsDura time.Duration done chan struct{} diff --git a/balancer/rls/internal/proto/grpc_lookup_v1/rls_grpc.pb.go b/balancer/rls/internal/proto/grpc_lookup_v1/rls_grpc.pb.go index 6e4145dd5..79fa758f7 100644 --- a/balancer/rls/internal/proto/grpc_lookup_v1/rls_grpc.pb.go +++ b/balancer/rls/internal/proto/grpc_lookup_v1/rls_grpc.pb.go @@ -39,12 +39,14 @@ func (c *routeLookupServiceClient) RouteLookup(ctx context.Context, in *RouteLoo } // RouteLookupServiceServer is the server API for RouteLookupService service. +// All implementations should embed UnimplementedRouteLookupServiceServer +// for forward compatibility type RouteLookupServiceServer interface { // Lookup returns a target for a single key. RouteLookup(context.Context, *RouteLookupRequest) (*RouteLookupResponse, error) } -// UnimplementedRouteLookupServiceServer can be embedded to have forward compatible implementations. +// UnimplementedRouteLookupServiceServer should be embedded to have forward compatible implementations. type UnimplementedRouteLookupServiceServer struct { } diff --git a/balancer/rls/internal/testutils/fakeserver/fakeserver.go b/balancer/rls/internal/testutils/fakeserver/fakeserver.go index 93947da4c..479e30364 100644 --- a/balancer/rls/internal/testutils/fakeserver/fakeserver.go +++ b/balancer/rls/internal/testutils/fakeserver/fakeserver.go @@ -49,6 +49,7 @@ type Response struct { // Server is a fake implementation of RLS. It exposes channels to send/receive // RLS requests and responses. type Server struct { + rlsgrpc.UnimplementedRouteLookupServiceServer RequestChan *testutils.Channel ResponseChan chan Response Address string diff --git a/benchmark/benchmark.go b/benchmark/benchmark.go index e844bb1ea..d82b61c9c 100644 --- a/benchmark/benchmark.go +++ b/benchmark/benchmark.go @@ -60,6 +60,7 @@ func NewPayload(t testpb.PayloadType, size int) *testpb.Payload { } type testServer struct { + testpb.UnimplementedBenchmarkServiceServer } func (s *testServer) UnaryCall(ctx context.Context, in *testpb.SimpleRequest) (*testpb.SimpleResponse, error) { @@ -141,6 +142,7 @@ func (s *testServer) UnconstrainedStreamingCall(stream testpb.BenchmarkService_U // byteBufServer is a gRPC server that sends and receives byte buffer. // The purpose is to benchmark the gRPC performance without protobuf serialization/deserialization overhead. type byteBufServer struct { + testpb.UnimplementedBenchmarkServiceServer respSize int32 } diff --git a/benchmark/grpc_testing/services_grpc.pb.go b/benchmark/grpc_testing/services_grpc.pb.go index e923f72c5..385870ae5 100644 --- a/benchmark/grpc_testing/services_grpc.pb.go +++ b/benchmark/grpc_testing/services_grpc.pb.go @@ -108,6 +108,8 @@ func (x *benchmarkServiceUnconstrainedStreamingCallClient) Recv() (*SimpleRespon } // BenchmarkServiceServer is the server API for BenchmarkService service. +// All implementations should embed UnimplementedBenchmarkServiceServer +// for forward compatibility type BenchmarkServiceServer interface { // One request followed by one response. // The server returns the client payload as-is. @@ -120,7 +122,7 @@ type BenchmarkServiceServer interface { UnconstrainedStreamingCall(BenchmarkService_UnconstrainedStreamingCallServer) error } -// UnimplementedBenchmarkServiceServer can be embedded to have forward compatible implementations. +// UnimplementedBenchmarkServiceServer should be embedded to have forward compatible implementations. type UnimplementedBenchmarkServiceServer struct { } @@ -347,6 +349,8 @@ func (c *workerServiceClient) QuitWorker(ctx context.Context, in *Void, opts ... } // WorkerServiceServer is the server API for WorkerService service. +// All implementations should embed UnimplementedWorkerServiceServer +// for forward compatibility type WorkerServiceServer interface { // Start server with specified workload. // First request sent specifies the ServerConfig followed by ServerStatus @@ -368,7 +372,7 @@ type WorkerServiceServer interface { QuitWorker(context.Context, *Void) (*Void, error) } -// UnimplementedWorkerServiceServer can be embedded to have forward compatible implementations. +// UnimplementedWorkerServiceServer should be embedded to have forward compatible implementations. type UnimplementedWorkerServiceServer struct { } diff --git a/benchmark/worker/main.go b/benchmark/worker/main.go index 2b760f54f..fba451c4f 100644 --- a/benchmark/worker/main.go +++ b/benchmark/worker/main.go @@ -73,6 +73,7 @@ func (byteBufCodec) String() string { // workerServer implements WorkerService rpc handlers. // It can create benchmarkServer or benchmarkClient on demand. type workerServer struct { + testpb.UnimplementedWorkerServiceServer stop chan<- bool serverPort int } diff --git a/channelz/grpc_channelz_v1/channelz_grpc.pb.go b/channelz/grpc_channelz_v1/channelz_grpc.pb.go index bacb448d1..20e1fe709 100644 --- a/channelz/grpc_channelz_v1/channelz_grpc.pb.go +++ b/channelz/grpc_channelz_v1/channelz_grpc.pb.go @@ -106,6 +106,8 @@ func (c *channelzClient) GetSocket(ctx context.Context, in *GetSocketRequest, op } // ChannelzServer is the server API for Channelz service. +// All implementations should embed UnimplementedChannelzServer +// for forward compatibility type ChannelzServer interface { // Gets all root channels (i.e. channels the application has directly // created). This does not include subchannels nor non-top level channels. @@ -124,7 +126,7 @@ type ChannelzServer interface { GetSocket(context.Context, *GetSocketRequest) (*GetSocketResponse, error) } -// UnimplementedChannelzServer can be embedded to have forward compatible implementations. +// UnimplementedChannelzServer should be embedded to have forward compatible implementations. type UnimplementedChannelzServer struct { } diff --git a/channelz/service/service.go b/channelz/service/service.go index b7650b3b2..702b74c03 100644 --- a/channelz/service/service.go +++ b/channelz/service/service.go @@ -48,7 +48,9 @@ func newCZServer() channelzgrpc.ChannelzServer { return &serverImpl{} } -type serverImpl struct{} +type serverImpl struct { + channelzgrpc.UnimplementedChannelzServer +} func connectivityStateToProto(s connectivity.State) *channelzpb.ChannelConnectivityState { switch s { diff --git a/cmd/protoc-gen-go-grpc/README.md b/cmd/protoc-gen-go-grpc/README.md new file mode 100644 index 000000000..f76e419a2 --- /dev/null +++ b/cmd/protoc-gen-go-grpc/README.md @@ -0,0 +1,21 @@ +# protoc-gen-go-grpc + +This tool generates Go language bindings of `service`s in protobuf definition +files for gRPC. For usage information, please see our [quick start +guide](https://grpc.io/docs/languages/go/quickstart/). + +## Future-proofing services + +By default, to register services using the methods generated by this tool, the +service implementations must embed the corresponding +`UnimplementedServer` for future compatibility. This is a behavior +change from the grpc code generator previously included with `protoc-gen-go`. +To restore this behavior, set the option `requireUnimplementedServers=false`. +E.g.: + +``` + protoc --go-grpc_out=requireUnimplementedServers=false[,other options...]:. \ +``` + +Note that this is not recommended, and the option is only provided to restore +backward compatibility with previously-generated code. diff --git a/cmd/protoc-gen-go-grpc/grpc.go b/cmd/protoc-gen-go-grpc/grpc.go index 38d444fc7..4f78bdd46 100644 --- a/cmd/protoc-gen-go-grpc/grpc.go +++ b/cmd/protoc-gen-go-grpc/grpc.go @@ -119,9 +119,16 @@ func genService(gen *protogen.Plugin, file *protogen.File, g *protogen.Generated } } + mustOrShould := "must" + if !*requireUnimplemented { + mustOrShould = "should" + } + // Server interface. serverType := service.GoName + "Server" g.P("// ", serverType, " is the server API for ", service.GoName, " service.") + g.P("// All implementations ", mustOrShould, " embed Unimplemented", serverType) + g.P("// for forward compatibility") if service.Desc.Options().(*descriptorpb.ServiceOptions).GetDeprecated() { g.P("//") g.P(deprecationComment) @@ -136,11 +143,14 @@ func genService(gen *protogen.Plugin, file *protogen.File, g *protogen.Generated g.P(method.Comments.Leading, serverSignature(g, method)) } + if *requireUnimplemented { + g.P("mustEmbedUnimplemented", serverType, "()") + } g.P("}") g.P() // Server Unimplemented struct for forward compatibility. - g.P("// Unimplemented", serverType, " can be embedded to have forward compatible implementations.") + g.P("// Unimplemented", serverType, " ", mustOrShould, " be embedded to have forward compatible implementations.") g.P("type Unimplemented", serverType, " struct {") g.P("}") g.P() @@ -153,6 +163,9 @@ func genService(gen *protogen.Plugin, file *protogen.File, g *protogen.Generated g.P("return ", nilArg, statusPackage.Ident("Errorf"), "(", codesPackage.Ident("Unimplemented"), `, "method `, method.GoName, ` not implemented")`) g.P("}") } + if *requireUnimplemented { + g.P("func (*Unimplemented", serverType, ") mustEmbedUnimplemented", serverType, "() {}") + } g.P() // Server registration. diff --git a/cmd/protoc-gen-go-grpc/main.go b/cmd/protoc-gen-go-grpc/main.go index dac0be207..a8555fad2 100644 --- a/cmd/protoc-gen-go-grpc/main.go +++ b/cmd/protoc-gen-go-grpc/main.go @@ -31,11 +31,20 @@ package main import ( + "flag" + "google.golang.org/protobuf/compiler/protogen" ) +var requireUnimplemented *bool + func main() { - protogen.Options{}.Run(func(gen *protogen.Plugin) error { + var flags flag.FlagSet + requireUnimplemented = flags.Bool("requireUnimplementedServers", true, "unset to match legacy behavior") + + protogen.Options{ + ParamFunc: flags.Set, + }.Run(func(gen *protogen.Plugin) error { for _, f := range gen.Files { if !f.Generate { continue diff --git a/credentials/alts/internal/proto/grpc_gcp/handshaker_grpc.pb.go b/credentials/alts/internal/proto/grpc_gcp/handshaker_grpc.pb.go index 75c2e4732..0e973b825 100644 --- a/credentials/alts/internal/proto/grpc_gcp/handshaker_grpc.pb.go +++ b/credentials/alts/internal/proto/grpc_gcp/handshaker_grpc.pb.go @@ -66,6 +66,8 @@ func (x *handshakerServiceDoHandshakeClient) Recv() (*HandshakerResp, error) { } // HandshakerServiceServer is the server API for HandshakerService service. +// All implementations should embed UnimplementedHandshakerServiceServer +// for forward compatibility type HandshakerServiceServer interface { // Handshaker service accepts a stream of handshaker request, returning a // stream of handshaker response. Client is expected to send exactly one @@ -76,7 +78,7 @@ type HandshakerServiceServer interface { DoHandshake(HandshakerService_DoHandshakeServer) error } -// UnimplementedHandshakerServiceServer can be embedded to have forward compatible implementations. +// UnimplementedHandshakerServiceServer should be embedded to have forward compatible implementations. type UnimplementedHandshakerServiceServer struct { } diff --git a/examples/features/proto/echo/echo_grpc.pb.go b/examples/features/proto/echo/echo_grpc.pb.go index 38be6f65c..ff3664353 100644 --- a/examples/features/proto/echo/echo_grpc.pb.go +++ b/examples/features/proto/echo/echo_grpc.pb.go @@ -142,6 +142,8 @@ func (x *echoBidirectionalStreamingEchoClient) Recv() (*EchoResponse, error) { } // EchoServer is the server API for Echo service. +// All implementations should embed UnimplementedEchoServer +// for forward compatibility type EchoServer interface { // UnaryEcho is unary echo. UnaryEcho(context.Context, *EchoRequest) (*EchoResponse, error) @@ -153,7 +155,7 @@ type EchoServer interface { BidirectionalStreamingEcho(Echo_BidirectionalStreamingEchoServer) error } -// UnimplementedEchoServer can be embedded to have forward compatible implementations. +// UnimplementedEchoServer should be embedded to have forward compatible implementations. type UnimplementedEchoServer struct { } diff --git a/examples/helloworld/helloworld/helloworld_grpc.pb.go b/examples/helloworld/helloworld/helloworld_grpc.pb.go index ac8135295..435df1a0e 100644 --- a/examples/helloworld/helloworld/helloworld_grpc.pb.go +++ b/examples/helloworld/helloworld/helloworld_grpc.pb.go @@ -39,12 +39,14 @@ func (c *greeterClient) SayHello(ctx context.Context, in *HelloRequest, opts ... } // GreeterServer is the server API for Greeter service. +// All implementations should embed UnimplementedGreeterServer +// for forward compatibility type GreeterServer interface { // Sends a greeting SayHello(context.Context, *HelloRequest) (*HelloReply, error) } -// UnimplementedGreeterServer can be embedded to have forward compatible implementations. +// UnimplementedGreeterServer should be embedded to have forward compatible implementations. type UnimplementedGreeterServer struct { } diff --git a/examples/route_guide/routeguide/route_guide_grpc.pb.go b/examples/route_guide/routeguide/route_guide_grpc.pb.go index 326a7683e..9ae8b4483 100644 --- a/examples/route_guide/routeguide/route_guide_grpc.pb.go +++ b/examples/route_guide/routeguide/route_guide_grpc.pb.go @@ -158,6 +158,8 @@ func (x *routeGuideRouteChatClient) Recv() (*RouteNote, error) { } // RouteGuideServer is the server API for RouteGuide service. +// All implementations should embed UnimplementedRouteGuideServer +// for forward compatibility type RouteGuideServer interface { // A simple RPC. // @@ -185,7 +187,7 @@ type RouteGuideServer interface { RouteChat(RouteGuide_RouteChatServer) error } -// UnimplementedRouteGuideServer can be embedded to have forward compatible implementations. +// UnimplementedRouteGuideServer should be embedded to have forward compatible implementations. type UnimplementedRouteGuideServer struct { } diff --git a/health/grpc_health_v1/health_grpc.pb.go b/health/grpc_health_v1/health_grpc.pb.go index 28cd72ea6..f87e3c92a 100644 --- a/health/grpc_health_v1/health_grpc.pb.go +++ b/health/grpc_health_v1/health_grpc.pb.go @@ -88,6 +88,8 @@ func (x *healthWatchClient) Recv() (*HealthCheckResponse, error) { } // HealthServer is the server API for Health service. +// All implementations should embed UnimplementedHealthServer +// for forward compatibility type HealthServer interface { // If the requested service is unknown, the call will fail with status // NOT_FOUND. @@ -110,7 +112,7 @@ type HealthServer interface { Watch(*HealthCheckRequest, Health_WatchServer) error } -// UnimplementedHealthServer can be embedded to have forward compatible implementations. +// UnimplementedHealthServer should be embedded to have forward compatible implementations. type UnimplementedHealthServer struct { } diff --git a/health/server.go b/health/server.go index 6b6512424..ed2b3df70 100644 --- a/health/server.go +++ b/health/server.go @@ -33,6 +33,7 @@ import ( // Server implements `service Health`. type Server struct { + healthgrpc.UnimplementedHealthServer mu sync.RWMutex // If shutdown is true, it's expected all serving status is NOT_SERVING, and // will stay in NOT_SERVING. diff --git a/interop/fake_grpclb/fake_grpclb.go b/interop/fake_grpclb/fake_grpclb.go index f6d55045e..3b2177ef0 100644 --- a/interop/fake_grpclb/fake_grpclb.go +++ b/interop/fake_grpclb/fake_grpclb.go @@ -48,6 +48,7 @@ var ( ) type loadBalancerServer struct { + lbpb.UnimplementedLoadBalancerServer serverListResponse *lbpb.LoadBalanceResponse } diff --git a/interop/grpc_testing/test_grpc.pb.go b/interop/grpc_testing/test_grpc.pb.go index d731f4643..07b555a3f 100644 --- a/interop/grpc_testing/test_grpc.pb.go +++ b/interop/grpc_testing/test_grpc.pb.go @@ -194,6 +194,8 @@ func (x *testServiceHalfDuplexCallClient) Recv() (*StreamingOutputCallResponse, } // TestServiceServer is the server API for TestService service. +// All implementations should embed UnimplementedTestServiceServer +// for forward compatibility type TestServiceServer interface { // One empty request followed by one empty response. EmptyCall(context.Context, *Empty) (*Empty, error) @@ -217,7 +219,7 @@ type TestServiceServer interface { HalfDuplexCall(TestService_HalfDuplexCallServer) error } -// UnimplementedTestServiceServer can be embedded to have forward compatible implementations. +// UnimplementedTestServiceServer should be embedded to have forward compatible implementations. type UnimplementedTestServiceServer struct { } @@ -445,12 +447,14 @@ func (c *unimplementedServiceClient) UnimplementedCall(ctx context.Context, in * } // UnimplementedServiceServer is the server API for UnimplementedService service. +// All implementations should embed UnimplementedUnimplementedServiceServer +// for forward compatibility type UnimplementedServiceServer interface { // A call that no server should implement UnimplementedCall(context.Context, *Empty) (*Empty, error) } -// UnimplementedUnimplementedServiceServer can be embedded to have forward compatible implementations. +// UnimplementedUnimplementedServiceServer should be embedded to have forward compatible implementations. type UnimplementedUnimplementedServiceServer struct { } @@ -519,12 +523,14 @@ func (c *loadBalancerStatsServiceClient) GetClientStats(ctx context.Context, in } // LoadBalancerStatsServiceServer is the server API for LoadBalancerStatsService service. +// All implementations should embed UnimplementedLoadBalancerStatsServiceServer +// for forward compatibility type LoadBalancerStatsServiceServer interface { // Gets the backend distribution for RPCs sent by a test client. GetClientStats(context.Context, *LoadBalancerStatsRequest) (*LoadBalancerStatsResponse, error) } -// UnimplementedLoadBalancerStatsServiceServer can be embedded to have forward compatible implementations. +// UnimplementedLoadBalancerStatsServiceServer should be embedded to have forward compatible implementations. type UnimplementedLoadBalancerStatsServiceServer struct { } diff --git a/interop/test_utils.go b/interop/test_utils.go index 63ba6a5eb..74e839031 100644 --- a/interop/test_utils.go +++ b/interop/test_utils.go @@ -672,6 +672,7 @@ func DoPickFirstUnary(tc testpb.TestServiceClient) { } type testServer struct { + testpb.UnimplementedTestServiceServer } // NewTestServer creates a test server for test service. diff --git a/interop/xds/client/client.go b/interop/xds/client/client.go index 009ad26f9..44fbf1e6d 100644 --- a/interop/xds/client/client.go +++ b/interop/xds/client/client.go @@ -60,7 +60,9 @@ var ( watchers = make(map[statsWatcherKey]*statsWatcher) ) -type statsService struct{} +type statsService struct { + testpb.UnimplementedLoadBalancerStatsServiceServer +} // Wait for the next LoadBalancerStatsRequest.GetNumRpcs to start and complete, // and return the distribution of remote peers. This is essentially a clientside diff --git a/profiling/proto/service_grpc.pb.go b/profiling/proto/service_grpc.pb.go index 87f1b74b7..aed8d5876 100644 --- a/profiling/proto/service_grpc.pb.go +++ b/profiling/proto/service_grpc.pb.go @@ -51,6 +51,8 @@ func (c *profilingClient) GetStreamStats(ctx context.Context, in *GetStreamStats } // ProfilingServer is the server API for Profiling service. +// All implementations should embed UnimplementedProfilingServer +// for forward compatibility type ProfilingServer interface { // Enable allows users to toggle profiling on and off remotely. Enable(context.Context, *EnableRequest) (*EnableResponse, error) @@ -59,7 +61,7 @@ type ProfilingServer interface { GetStreamStats(context.Context, *GetStreamStatsRequest) (*GetStreamStatsResponse, error) } -// UnimplementedProfilingServer can be embedded to have forward compatible implementations. +// UnimplementedProfilingServer should be embedded to have forward compatible implementations. type UnimplementedProfilingServer struct { } diff --git a/profiling/service/service.go b/profiling/service/service.go index a36b8bdda..52a7ce789 100644 --- a/profiling/service/service.go +++ b/profiling/service/service.go @@ -76,6 +76,7 @@ func Init(pc *ProfilingConfig) error { } type profilingServer struct { + ppb.UnimplementedProfilingServer drainMutex sync.Mutex } diff --git a/reflection/grpc_reflection_v1alpha/reflection_grpc.pb.go b/reflection/grpc_reflection_v1alpha/reflection_grpc.pb.go index f04e2d4bb..2294b2c6c 100644 --- a/reflection/grpc_reflection_v1alpha/reflection_grpc.pb.go +++ b/reflection/grpc_reflection_v1alpha/reflection_grpc.pb.go @@ -62,13 +62,15 @@ func (x *serverReflectionServerReflectionInfoClient) Recv() (*ServerReflectionRe } // ServerReflectionServer is the server API for ServerReflection service. +// All implementations should embed UnimplementedServerReflectionServer +// for forward compatibility type ServerReflectionServer interface { // The reflection service is structured as a bidirectional stream, ensuring // all related requests go to a single server. ServerReflectionInfo(ServerReflection_ServerReflectionInfoServer) error } -// UnimplementedServerReflectionServer can be embedded to have forward compatible implementations. +// UnimplementedServerReflectionServer should be embedded to have forward compatible implementations. type UnimplementedServerReflectionServer struct { } diff --git a/reflection/grpc_testing/test_grpc.pb.go b/reflection/grpc_testing/test_grpc.pb.go index 52eac202b..95cd2bab1 100644 --- a/reflection/grpc_testing/test_grpc.pb.go +++ b/reflection/grpc_testing/test_grpc.pb.go @@ -70,12 +70,14 @@ func (x *searchServiceStreamingSearchClient) Recv() (*SearchResponse, error) { } // SearchServiceServer is the server API for SearchService service. +// All implementations should embed UnimplementedSearchServiceServer +// for forward compatibility type SearchServiceServer interface { Search(context.Context, *SearchRequest) (*SearchResponse, error) StreamingSearch(SearchService_StreamingSearchServer) error } -// UnimplementedSearchServiceServer can be embedded to have forward compatible implementations. +// UnimplementedSearchServiceServer should be embedded to have forward compatible implementations. type UnimplementedSearchServiceServer struct { } diff --git a/reflection/serverreflection.go b/reflection/serverreflection.go index de3e132f0..7b6dd414a 100644 --- a/reflection/serverreflection.go +++ b/reflection/serverreflection.go @@ -55,6 +55,7 @@ import ( ) type serverReflectionServer struct { + rpb.UnimplementedServerReflectionServer s *grpc.Server initSymbols sync.Once diff --git a/regenerate.sh b/regenerate.sh index 6f47daf94..987bc2025 100755 --- a/regenerate.sh +++ b/regenerate.sh @@ -57,7 +57,7 @@ SOURCES=( OPTS=Mgrpc/service_config/service_config.proto=/internal/proto/grpc_service_config for src in ${SOURCES[@]}; do echo "protoc ${src}" - protoc --go_out=${OPTS}:${WORKDIR}/out --go-grpc_out=${OPTS}:${WORKDIR}/out \ + protoc --go_out=${OPTS}:${WORKDIR}/out --go-grpc_out=${OPTS},requireUnimplementedServers=false:${WORKDIR}/out \ -I"." \ -I${WORKDIR}/grpc-proto \ -I${WORKDIR}/googleapis \ diff --git a/stats/grpc_testing/test_grpc.pb.go b/stats/grpc_testing/test_grpc.pb.go index a12bccebc..98da3340b 100644 --- a/stats/grpc_testing/test_grpc.pb.go +++ b/stats/grpc_testing/test_grpc.pb.go @@ -145,6 +145,8 @@ func (x *testServiceServerStreamCallClient) Recv() (*SimpleResponse, error) { } // TestServiceServer is the server API for TestService service. +// All implementations should embed UnimplementedTestServiceServer +// for forward compatibility type TestServiceServer interface { // One request followed by one response. // The server returns the client id as-is. @@ -159,7 +161,7 @@ type TestServiceServer interface { ServerStreamCall(*SimpleRequest, TestService_ServerStreamCallServer) error } -// UnimplementedTestServiceServer can be embedded to have forward compatible implementations. +// UnimplementedTestServiceServer should be embedded to have forward compatible implementations. type UnimplementedTestServiceServer struct { } diff --git a/stress/client/main.go b/stress/client/main.go index 86d7539ae..b8f2229a5 100644 --- a/stress/client/main.go +++ b/stress/client/main.go @@ -144,6 +144,7 @@ func (g *gauge) get() int64 { // server implements metrics server functions. type server struct { + metricspb.UnimplementedMetricsServiceServer mutex sync.RWMutex // gauges is a map from /stress_test/server_/channel_/stub_/qps to its qps gauge. gauges map[string]*gauge diff --git a/stress/grpc_testing/metrics_grpc.pb.go b/stress/grpc_testing/metrics_grpc.pb.go index 06c8a6b5f..3a232ff85 100644 --- a/stress/grpc_testing/metrics_grpc.pb.go +++ b/stress/grpc_testing/metrics_grpc.pb.go @@ -74,6 +74,8 @@ func (c *metricsServiceClient) GetGauge(ctx context.Context, in *GaugeRequest, o } // MetricsServiceServer is the server API for MetricsService service. +// All implementations should embed UnimplementedMetricsServiceServer +// for forward compatibility type MetricsServiceServer interface { // Returns the values of all the gauges that are currently being maintained by // the service @@ -82,7 +84,7 @@ type MetricsServiceServer interface { GetGauge(context.Context, *GaugeRequest) (*GaugeResponse, error) } -// UnimplementedMetricsServiceServer can be embedded to have forward compatible implementations. +// UnimplementedMetricsServiceServer should be embedded to have forward compatible implementations. type UnimplementedMetricsServiceServer struct { } diff --git a/test/grpc_testing/test_grpc.pb.go b/test/grpc_testing/test_grpc.pb.go index a211dcab9..2340ac05e 100644 --- a/test/grpc_testing/test_grpc.pb.go +++ b/test/grpc_testing/test_grpc.pb.go @@ -194,6 +194,8 @@ func (x *testServiceHalfDuplexCallClient) Recv() (*StreamingOutputCallResponse, } // TestServiceServer is the server API for TestService service. +// All implementations should embed UnimplementedTestServiceServer +// for forward compatibility type TestServiceServer interface { // One empty request followed by one empty response. EmptyCall(context.Context, *Empty) (*Empty, error) @@ -217,7 +219,7 @@ type TestServiceServer interface { HalfDuplexCall(TestService_HalfDuplexCallServer) error } -// UnimplementedTestServiceServer can be embedded to have forward compatible implementations. +// UnimplementedTestServiceServer should be embedded to have forward compatible implementations. type UnimplementedTestServiceServer struct { }