Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

grpc with mustEmbedUnimplemented*** method

Recently, grpc-go introduced the mustEmbedUnimplemented*** method. It is used for forward compatibility.

In simple terms, I am unable to understand how it is helping and how earlier without it what problems we were facing? In my structs now I use to add the following statement but, I don't know why...

type server struct {
     pdfpb.UnimplementedGreetServiceServer
}

In Github issue - https://github.com/grpc/grpc-go/issues/3669 they debated over it, can someone please explain in simple terms how it is helping and how earlier without it what problems we were facing?

like image 592
Parth Wadhwa Avatar asked Nov 30 '20 18:11

Parth Wadhwa


3 Answers

That was quite basic.

UnimplementedGreetServiceServer is a struct with all implemented methods.

When I add pdfpb.UnimplementedGreetServiceServer I am able to call UnimplementedGreetServiceServer defined methods.

That's how, if I add more RPC services in the proto file, then I don't need to add all RPC methods leading to forward compatibility.

Demo code is available at: https://github.com/parthw/fun-coding/tree/main/golang/understanding-grpc-change

like image 72
Parth Wadhwa Avatar answered Oct 17 '22 06:10

Parth Wadhwa


This error comes newer versions of the protoc-gen-grpc-go compiler. Server implementations must now be forward-compatible.

Before this change, whenever you registered a server implementation, you would do something like this:

        pb.RegisterFooBarServiceServer(
            server,
            &FooBarServer{}, // or whatever you use to construct the server impl
        )

Which would result in a compile-time error in case your server has some missing method implementations.

With the newer proto compiler version, forward-compatibility becomes opt-out, which means two things:

  1. you must now embed UnimplementedFooBarServiceServer, as the error message suggests. As I said, this will not produce compiler errors when you do not explicitly implement new methods (this is what forward compatibility means). Though it will result in a run-time error with codes.Unimplemented if you attempt to call an RPC that you didn't (or forgot) to explicitly implement.

  2. you can still opt-out of forward compatibility by embedding instead UnsafeFooBarServiceServer (with Unsafe prefix). This interface simply declares the mustEmbedUnimplementedFooBarServiceServer() method which makes the error in the question go away, without forgoing a compiler errors in case you didn't explicitly implement the new handlers.

So for example:

// Implements the grpc FooBarServiceServer
type FooBarService struct {
    grpc.UnsafeFooBarServiceServer // consciously opt-out of forward compatibility
    // other fields
}

You can also generate code without forward compatibility by setting an option on protoc-gen-grpc-go plugin (source):

protoc --go-grpc_out=require_unimplemented_servers=false:.

Note the :. after the --go-grpc_out option is used to set the path element.

like image 10
blackgreen Avatar answered Oct 17 '22 06:10

blackgreen


For anyone that still have problems with mustEmbededUnimplementedServiceServer as suggested on the Github Issue. the best solution is just to update your ServerStruct.

Ex.

type AuthenticationServiceServer struct {
}

To.

type AuthenticationServiceServer struct {
    service.UnimplementedAuthenticationServiceServer
}

that will solve the exception throw by Go when doing this.

grpcService.RegisterAuthenticationServiceServer(grpcServer, controller.AuthenticationServiceServer{})
like image 3
Luis Cardoza Bird Avatar answered Oct 17 '22 06:10

Luis Cardoza Bird