akka / akka-grpc

A platform to build and run apps that are elastic, agile, and resilient. SDK, libraries, and hosted environments.
https://doc.akka.io/libraries/akka-grpc/current/
Other
431 stars 124 forks source link

Support for richer error responses / google.rpc.Status #577

Open ctoomey opened 5 years ago

ctoomey commented 5 years ago

Currently there's no standard way to return rich error responses, just the code and optional description of io.grpc.Status via GrpcServiceException.

Google has introduced and uses google.rpc.Status and is developing client library support for it, per here.

See also the discussion of this richer model in the gRPC error handling guide.

Richer error responses are something our team would like to be able to support in a standard way. Is adding support for this on the akka-grpc roadmap?

raboof commented 5 years ago

This sounds great!

ghost commented 4 years ago

@raboof Is this on the roadmap? It's preventing us from moving to akka-grpc. We utilize rich error responses so details, especially BadRequest FieldViolations, are machine-readable by clients.

raboof commented 4 years ago

Hi @rockywarren-vertex! thanks for expressing your interest in this feature, that is useful to prioritize it.

We're currently working towards 1.0.0 (#827) and we're not planning to work on this feature for that release. That said, it does seem like a very useful feature, so a contribution in this area would definitely be welcome.

If I understand correctly, those detailed error responses are encoded as custom metadata fields in the trailing headers.

One simple thing we could do is change the error handler from Throwable => Status to Throwable => List[HttpHeader], that way you could implement detailed error responses in your own error handler.

When we want to support this more natively we can introduce some new exception types, and extend the default error handler to turn those into the standard rich error types. Since there's already code generation in the akka-grpc-runtime subproject that might not be hard anymore.

drmontgomery commented 4 years ago

Hi, all. I just submitted a pull request that implements support for returning custom headers from GrpcExceptionHandler (and adds them to GrpcServiceException as well).

I tried to keep the changes fairly minimal. Unfortunately, there was a fair amount of incidental complexity due to the need to support both javadsl and scaladsl HttpHeaders in the interfaces.

Things that I think could be improved:

  1. It feels like returning HttpHeaders is a little low-level. It also means that user code is going to have to duplicate the Base64 encoding functionality to send binary data to clients. Perhaps we should be returning a Map of String and Binary metadata entries instead, and handling the encoding internally?
  2. As a user, it feels like the exception handler should be a PartialFunction[Throwable, GrpcErrorResponse], not a Function[ActorSystem, PartialFunction[Throwable, GrpcErrorResponse]]. (The dependency on ActorSystem seems to be mainly a quirk of the default exception handler implementation, not a logical requirement.) Perhaps we should be using user-provided partial function with an orElse to the default implementation?

I bring these up for discussion mainly because it will presumably be more difficult to change them after 1.0.0.

Anyway, hope this is helpful. Please let me know if there are any changes you'd like me to make.

ctoomey commented 4 years ago

Thanks for doing this @drmontgomery !

sebastian-alfers commented 2 years ago

Feel free to have a look at this contribution to document how the "Rich error model" can currently be used with Akka gRPC.

However it is likely what in the future there will be a more native api in Akka gRPC that will require less boilerplate than what the current state of the PR suggests.

The reason for adding this "workaround" to documentation is that it is not when this native api will land in a release and how it will look like.

sebastian-alfers commented 2 years ago

@ctoomey @rockywarren-vertex The docs now include sections how to handle this on the server as well as on the client.