Skip to content

Commit 1250867

Browse files
committed
Merge pull request go-kit#287 from go-kit/addsvc-errors
examples/addsvc: more sophisticated error encoding
2 parents 0db02c6 + 94228a7 commit 1250867

File tree

8 files changed

+144
-36
lines changed

8 files changed

+144
-36
lines changed

examples/addsvc/endpoints.go

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ func (e Endpoints) Sum(ctx context.Context, a, b int) (int, error) {
4242
if err != nil {
4343
return 0, err
4444
}
45-
return response.(sumResponse).V, nil
45+
return response.(sumResponse).V, response.(sumResponse).Err
4646
}
4747

4848
// Concat implements Service. Primarily useful in a client.
@@ -52,7 +52,7 @@ func (e Endpoints) Concat(ctx context.Context, a, b string) (string, error) {
5252
if err != nil {
5353
return "", err
5454
}
55-
return response.(concatResponse).V, err
55+
return response.(concatResponse).V, response.(concatResponse).Err
5656
}
5757

5858
// MakeSumEndpoint returns an endpoint that invokes Sum on the service.
@@ -61,11 +61,12 @@ func MakeSumEndpoint(s Service) endpoint.Endpoint {
6161
return func(ctx context.Context, request interface{}) (response interface{}, err error) {
6262
sumReq := request.(sumRequest)
6363
v, err := s.Sum(ctx, sumReq.A, sumReq.B)
64-
if err != nil {
65-
return nil, err
64+
if err == ErrIntOverflow {
65+
return nil, err // special case; see comment on ErrIntOverflow
6666
}
6767
return sumResponse{
68-
V: v,
68+
V: v,
69+
Err: err,
6970
}, nil
7071
}
7172
}
@@ -76,11 +77,9 @@ func MakeConcatEndpoint(s Service) endpoint.Endpoint {
7677
return func(ctx context.Context, request interface{}) (response interface{}, err error) {
7778
concatReq := request.(concatRequest)
7879
v, err := s.Concat(ctx, concatReq.A, concatReq.B)
79-
if err != nil {
80-
return nil, err
81-
}
8280
return concatResponse{
83-
V: v,
81+
V: v,
82+
Err: err,
8483
}, nil
8584
}
8685
}
@@ -124,8 +123,14 @@ func EndpointLoggingMiddleware(logger log.Logger) endpoint.Middleware {
124123

125124
type sumRequest struct{ A, B int }
126125

127-
type sumResponse struct{ V int }
126+
type sumResponse struct {
127+
V int
128+
Err error
129+
}
128130

129131
type concatRequest struct{ A, B string }
130132

131-
type concatResponse struct{ V string }
133+
type concatResponse struct {
134+
V string
135+
Err error
136+
}

examples/addsvc/pb/addsvc.pb.go

Lines changed: 13 additions & 10 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

examples/addsvc/pb/addsvc.proto

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ message SumRequest {
2020
// The sum response contains the result of the calculation.
2121
message SumReply {
2222
int64 v = 1;
23+
string err = 2;
2324
}
2425

2526
// The Concat request contains two parameters.
@@ -31,4 +32,5 @@ message ConcatRequest {
3132
// The Concat response contains the result of the concatenation.
3233
message ConcatReply {
3334
string v = 1;
35+
string err = 2;
3436
}

examples/addsvc/service.go

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,17 +19,46 @@ type Service interface {
1919
Concat(ctx context.Context, a, b string) (string, error)
2020
}
2121

22+
// Business-domain errors like these may be served in two ways: returned
23+
// directly by endpoints, or bundled into the response struct. Both methods can
24+
// be made to work, but errors returned directly by endpoints are counted by
25+
// middlewares that check errors, like circuit breakers.
26+
//
27+
// If you don't want that behavior -- and you probably don't -- then it's better
28+
// to bundle errors into the response struct.
29+
2230
var (
2331
// ErrTwoZeroes is an arbitrary business rule for the Add method.
2432
ErrTwoZeroes = errors.New("can't sum two zeroes")
2533

26-
// ErrIntOverflow protects the Add method.
34+
// ErrIntOverflow protects the Add method. We've decided that this error
35+
// indicates a misbehaving service and should count against e.g. circuit
36+
// breakers. So, we return it directly in endpoints, to illustrate the
37+
// difference. In a real service, this probably wouldn't be the case.
2738
ErrIntOverflow = errors.New("integer overflow")
2839

2940
// ErrMaxSizeExceeded protects the Concat method.
3041
ErrMaxSizeExceeded = errors.New("result exceeds maximum size")
3142
)
3243

44+
// These annoying helper functions are required to translate Go error types to
45+
// and from strings, which is the type we use in our IDLs to represent errors.
46+
// There is special casing to treat empty strings as nil errors.
47+
48+
func str2err(s string) error {
49+
if s == "" {
50+
return nil
51+
}
52+
return errors.New(s)
53+
}
54+
55+
func err2str(err error) string {
56+
if err == nil {
57+
return ""
58+
}
59+
return err.Error()
60+
}
61+
3362
// NewBasicService returns a naïve, stateless implementation of Service.
3463
func NewBasicService() Service {
3564
return basicService{}

examples/addsvc/thrift/addsvc.thrift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
struct SumReply {
22
1: i64 value
3+
2: string err
34
}
45

56
struct ConcatReply {
67
1: string value
8+
2: string err
79
}
810

911
service AddService {

examples/addsvc/thrift/gen-go/addsvc/ttypes.go

Lines changed: 71 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

examples/addsvc/transport_grpc.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -76,30 +76,30 @@ func DecodeGRPCConcatRequest(_ context.Context, grpcReq interface{}) (interface{
7676
// gRPC sum reply to a user-domain sum response. Primarily useful in a client.
7777
func DecodeGRPCSumResponse(_ context.Context, grpcReply interface{}) (interface{}, error) {
7878
reply := grpcReply.(*pb.SumReply)
79-
return sumResponse{V: int(reply.V)}, nil
79+
return sumResponse{V: int(reply.V), Err: str2err(reply.Err)}, nil
8080
}
8181

8282
// DecodeGRPCConcatResponse is a transport/grpc.DecodeResponseFunc that converts
8383
// a gRPC concat reply to a user-domain concat response. Primarily useful in a
8484
// client.
8585
func DecodeGRPCConcatResponse(_ context.Context, grpcReply interface{}) (interface{}, error) {
8686
reply := grpcReply.(*pb.ConcatReply)
87-
return concatResponse{V: reply.V}, nil
87+
return concatResponse{V: reply.V, Err: str2err(reply.Err)}, nil
8888
}
8989

9090
// EncodeGRPCSumResponse is a transport/grpc.EncodeResponseFunc that converts a
9191
// user-domain sum response to a gRPC sum reply. Primarily useful in a server.
9292
func EncodeGRPCSumResponse(_ context.Context, response interface{}) (interface{}, error) {
9393
resp := response.(sumResponse)
94-
return &pb.SumReply{V: int64(resp.V)}, nil
94+
return &pb.SumReply{V: int64(resp.V), Err: err2str(resp.Err)}, nil
9595
}
9696

9797
// EncodeGRPCConcatResponse is a transport/grpc.EncodeResponseFunc that converts
9898
// a user-domain concat response to a gRPC concat reply. Primarily useful in a
9999
// server.
100100
func EncodeGRPCConcatResponse(_ context.Context, response interface{}) (interface{}, error) {
101101
resp := response.(concatResponse)
102-
return &pb.ConcatReply{V: resp.V}, nil
102+
return &pb.ConcatReply{V: resp.V, Err: err2str(resp.Err)}, nil
103103
}
104104

105105
// EncodeGRPCSumRequest is a transport/grpc.EncodeRequestFunc that converts a

0 commit comments

Comments
 (0)