add error handling example

This commit is contained in:
Dawid Wysokiński 2023-05-04 06:36:01 +02:00
parent 9069494e7f
commit bc61ba9c6e
Signed by: Kichiyaki
GPG Key ID: B5445E357FB8B892
3 changed files with 84 additions and 5 deletions

View File

@ -19,8 +19,10 @@ import (
"gitea.dwysokinski.me/Kichiyaki/grpc-g2a/proto"
"github.com/google/uuid"
"go.uber.org/zap"
"google.golang.org/genproto/googleapis/rpc/errdetails"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials"
"google.golang.org/grpc/status"
)
const defaultAddress = "localhost:50001"
@ -30,6 +32,8 @@ const (
exampleServer = "server"
exampleClient = "client"
exampleBidirectional = "bidirectional"
exampleJames = "james"
exampleJamesError = "jameserror"
)
func main() {
@ -64,6 +68,10 @@ func main() {
switch example {
case exampleUnary:
sayHello(ctx, client, logger)
case exampleJames:
sayHelloToJames(ctx, client, logger)
case exampleJamesError:
sayHelloToJamesError(ctx, client, logger)
case exampleServer:
sayHelloServerStream(ctx, client, logger)
case exampleClient:
@ -77,12 +85,16 @@ func main() {
func parseExample() string {
example := ""
flag.StringVar(
&example,
"example",
flag.StringVar(&example, "example", exampleUnary, fmt.Sprintf(
"%s, %s, %s, %s, %s or %s (default: %s)",
exampleUnary,
fmt.Sprintf("%s, %s, %s or %s (default: %s)", exampleUnary, exampleServer, exampleClient, exampleBidirectional, exampleUnary),
)
exampleJames,
exampleJamesError,
exampleServer,
exampleClient,
exampleBidirectional,
exampleUnary,
))
flag.Parse()
return example
}
@ -133,6 +145,46 @@ func sayHello(ctx context.Context, client proto.GreeterClient, logger *zap.Logge
logger.Info("reply received", zap.String("message", reply.GetMessage()))
}
func sayHelloToJames(ctx context.Context, client proto.GreeterClient, logger *zap.Logger) {
name := "James"
logger.Info("sending request", zap.String("name", name))
reply, err := client.SayHelloToJames(ctx, &proto.HelloRequest{Name: name})
if err != nil {
logger.Fatal("something went wrong while calling SayHello", zap.Error(err))
}
logger.Info("reply received", zap.String("message", reply.GetMessage()))
}
func sayHelloToJamesError(ctx context.Context, client proto.GreeterClient, logger *zap.Logger) {
name := "SomeoneElse"
logger.Info("sending request", zap.String("name", name))
reply, err := client.SayHelloToJames(ctx, &proto.HelloRequest{Name: name})
if err == nil {
logger.Info("unexpected reply received", zap.String("message", reply.GetMessage()))
return
}
st, ok := status.FromError(err)
if !ok {
logger.Fatal("received unexpected error", zap.Error(err))
}
var violations []string
for _, detail := range st.Details() {
switch d := detail.(type) {
case *errdetails.BadRequest:
for _, violation := range d.GetFieldViolations() {
violations = append(violations, violation.GetField()+": "+violation.GetDescription())
}
default:
logger.Debug("unhandled detail", zap.Any("detail", d))
}
}
logger.Info("received error", zap.Error(err), zap.Strings("violations", violations))
}
const (
namesLen = 20
)

View File

@ -19,6 +19,7 @@ import (
grpc_recovery "github.com/grpc-ecosystem/go-grpc-middleware/recovery"
grpc_ctxtags "github.com/grpc-ecosystem/go-grpc-middleware/tags"
"go.uber.org/zap"
"google.golang.org/genproto/googleapis/rpc/errdetails"
"google.golang.org/grpc"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/credentials"
@ -156,6 +157,31 @@ func (g *greeterServer) SayHello(_ context.Context, r *proto.HelloRequest) (*pro
}, nil
}
func (g *greeterServer) SayHelloToJames(_ context.Context, r *proto.HelloRequest) (*proto.HelloReply, error) {
name := r.GetName()
if name != "James" {
st, err := status.
New(codes.InvalidArgument, "invalid name").
WithDetails(&errdetails.BadRequest{
FieldViolations: []*errdetails.BadRequest_FieldViolation{
{
Field: "name",
Description: "must be James",
},
},
})
if err != nil {
return nil, status.New(codes.Internal, "internal server error").Err()
}
return nil, st.Err()
}
return &proto.HelloReply{
Message: buildHelloMsg(name),
}, nil
}
func (g *greeterServer) SayHelloServerStream(r *proto.MultiHelloRequest, stream proto.Greeter_SayHelloServerStreamServer) error {
for _, n := range r.GetNames() {
if err := stream.Send(&proto.HelloReply{

View File

@ -4,6 +4,7 @@ option go_package = "gitea.dwysokinski.me/Kichiyaki/grpc-g2a/proto";
service Greeter {
rpc SayHello (HelloRequest) returns (HelloReply) {}
rpc SayHelloToJames (HelloRequest) returns (HelloReply) {}
rpc SayHelloClientStream (stream HelloRequest) returns (MultiHelloReply) {}
rpc SayHelloServerStream (MultiHelloRequest) returns (stream HelloReply) {}
rpc SayHelloBidirectionalStream (stream HelloRequest) returns (stream HelloReply) {}