In general error handling is in my opinion one of the hardest parts of 
software engineering. :) Silly comments aside, in my limited experience, 
gRPC seems to encourage "just" returning a gRPC status code and a string. 
The examples I like to look at are the Google Cloud APIs. For example, the 
Spanner ExecuteSql says "if [...] the query fails with a 
FAILED_PRECONDITION error. Queries [...] might return ABORTED. If this 
occurs, the application should [...]"

So if you can map your application errors to gRPC errors and get what you 
want, that seems like the "recommended" way.

The other thing I have done in some cases is to redefine "success". For 
example, maybe the "Login" API should return an object with either the 
logged in credentials, or a detailed error if they can't be logged in for 
some reason?


Spanner ExecuteSql:

https://cloud.google.com/spanner/docs/reference/rpc/google.spanner.v1#google.spanner.v1.Spanner.ExecuteSql


Google Cloud API Design guide on errors:

https://cloud.google.com/apis/design/errors


On Tuesday, September 12, 2017 at 9:29:26 PM UTC-4, Francis Chuang wrote:
>
> I am working on an app built as a set of microservices. Each microservice 
> will be built using GRPC using Go. In front of these services, there will 
> be an API gateway (built using GraphQL).
>
> As an example, there is an authentication microservice that authenticates 
> users using their email address and password. There is a SignIn GRPC 
> service method that takes the email address, password and session id of the 
> user. If authentication is successful, we attach the user's id to their 
> session (using the session id).
>
> The problem is that if the authentication fails, we want to surface this 
> to the UI. In the GRPC method implementation, I can return GRPC status 
> codes, for example: return nil, status.Error(codes.InvalidArgument, "could 
> not find user by email address"). In order to work out specifically what is 
> wrong, the client calling this method would need to parse the error message 
> (which is not a great idea).
>
> I've thought about attaching extra details to the error. For example, 
> using bad request: 
> https://godoc.org/google.golang.org/genproto/googleapis/rpc/errdetails#BadRequest
>
> However, the method is littered with multiple copies of this in of each 
> RPC method:
>
> s, err := status.Newf(codes.InvalidArgument, "could not find user by email 
> address").WithDetails(&errdetails.BadRequest{
> FieldViolations: []*errdetails.BadRequest_FieldViolation{
> {
> Description: "EMAIL_ADDRESS_NOT_FOUND",
> Field: []string{"SignInRequest.email"},
> },
> },
> })
>
> if err != nil {
> return nil, status.Errorf(codes.Internal, "error marshaling status error: 
> %s", err)
> }
>
> return nil, s.Err()
>
> In addition, I also need to keep a list of error codes 
> (EMAIL_ADDRESS_NOT_FOUND) in the above example and make sure the clients 
> calling this method checks against them. The API gateway would then look at 
> the error code and surface the appropriate localized error messages to the 
> UI.
>
> The approaches I have tried do not appear to be very nice and have made 
> working on these RPC methods to be a chore and quite unpleasant.
>
> Has anyone else successfully solved this problem? If so, what were your 
> approaches?
>
> Cheers,
> Francis
>

-- 
You received this message because you are subscribed to the Google Groups 
"grpc.io" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].
Visit this group at https://groups.google.com/group/grpc-io.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/grpc-io/3eeb7ae2-595c-4640-a271-4e8af3e14310%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to