Codebase list golang-github-go-kit-kit / 1250867
Merge pull request #287 from go-kit/addsvc-errors examples/addsvc: more sophisticated error encoding Peter Bourgon 7 years ago
8 changed file(s) with 145 addition(s) and 37 deletion(s). Raw diff Collapse all Expand all
4141 if err != nil {
4242 return 0, err
4343 }
44 return response.(sumResponse).V, nil
44 return response.(sumResponse).V, response.(sumResponse).Err
4545 }
4646
4747 // Concat implements Service. Primarily useful in a client.
5151 if err != nil {
5252 return "", err
5353 }
54 return response.(concatResponse).V, err
54 return response.(concatResponse).V, response.(concatResponse).Err
5555 }
5656
5757 // MakeSumEndpoint returns an endpoint that invokes Sum on the service.
6060 return func(ctx context.Context, request interface{}) (response interface{}, err error) {
6161 sumReq := request.(sumRequest)
6262 v, err := s.Sum(ctx, sumReq.A, sumReq.B)
63 if err != nil {
64 return nil, err
63 if err == ErrIntOverflow {
64 return nil, err // special case; see comment on ErrIntOverflow
6565 }
6666 return sumResponse{
67 V: v,
67 V: v,
68 Err: err,
6869 }, nil
6970 }
7071 }
7576 return func(ctx context.Context, request interface{}) (response interface{}, err error) {
7677 concatReq := request.(concatRequest)
7778 v, err := s.Concat(ctx, concatReq.A, concatReq.B)
78 if err != nil {
79 return nil, err
80 }
8179 return concatResponse{
82 V: v,
80 V: v,
81 Err: err,
8382 }, nil
8483 }
8584 }
123122
124123 type sumRequest struct{ A, B int }
125124
126 type sumResponse struct{ V int }
125 type sumResponse struct {
126 V int
127 Err error
128 }
127129
128130 type concatRequest struct{ A, B string }
129131
130 type concatResponse struct{ V string }
132 type concatResponse struct {
133 V string
134 Err error
135 }
4646
4747 // The sum response contains the result of the calculation.
4848 type SumReply struct {
49 V int64 `protobuf:"varint,1,opt,name=v" json:"v,omitempty"`
49 V int64 `protobuf:"varint,1,opt,name=v" json:"v,omitempty"`
50 Err string `protobuf:"bytes,2,opt,name=err" json:"err,omitempty"`
5051 }
5152
5253 func (m *SumReply) Reset() { *m = SumReply{} }
6768
6869 // The Concat response contains the result of the concatenation.
6970 type ConcatReply struct {
70 V string `protobuf:"bytes,1,opt,name=v" json:"v,omitempty"`
71 V string `protobuf:"bytes,1,opt,name=v" json:"v,omitempty"`
72 Err string `protobuf:"bytes,2,opt,name=err" json:"err,omitempty"`
7173 }
7274
7375 func (m *ConcatReply) Reset() { *m = ConcatReply{} }
191193 }
192194
193195 var fileDescriptor0 = []byte{
194 // 174 bytes of a gzipped FileDescriptorProto
196 // 188 bytes of a gzipped FileDescriptorProto
195197 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xe2, 0xe2, 0x49, 0x4c, 0x49, 0x29,
196198 0x2e, 0x4b, 0xd6, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x62, 0x2a, 0x48, 0x52, 0xd2, 0xe0, 0xe2,
197199 0x0a, 0x2e, 0xcd, 0x0d, 0x4a, 0x2d, 0x2c, 0x4d, 0x2d, 0x2e, 0x11, 0xe2, 0xe1, 0x62, 0x4c, 0x94,
198200 0x60, 0x54, 0x60, 0xd4, 0x60, 0x0e, 0x62, 0x4c, 0x04, 0xf1, 0x92, 0x24, 0x98, 0x20, 0xbc, 0x24,
199 0x25, 0x09, 0x2e, 0x0e, 0xb0, 0xca, 0x82, 0x9c, 0x4a, 0x90, 0x4c, 0x19, 0x4c, 0x5d, 0x99, 0x92,
200 0x36, 0x17, 0xaf, 0x73, 0x7e, 0x5e, 0x72, 0x62, 0x09, 0x86, 0x31, 0x9c, 0x28, 0xc6, 0x70, 0x82,
201 0x8c, 0x91, 0xe6, 0xe2, 0x86, 0x29, 0x46, 0x31, 0x09, 0x28, 0x59, 0x66, 0x14, 0xc3, 0xc5, 0xec,
202 0x98, 0x92, 0x22, 0xa4, 0xca, 0xc5, 0x0c, 0xb4, 0x4a, 0x88, 0x4f, 0xaf, 0x20, 0x49, 0x0f, 0xe1,
203 0x3a, 0x29, 0x1e, 0x38, 0x1f, 0xa8, 0x53, 0x89, 0x41, 0x48, 0x8f, 0x8b, 0x0d, 0x62, 0x94, 0x90,
204 0x20, 0x48, 0x06, 0xc5, 0x0d, 0x52, 0xfc, 0xc8, 0x42, 0x60, 0xf5, 0x49, 0x6c, 0x60, 0x6f, 0x1b,
205 0x03, 0x02, 0x00, 0x00, 0xff, 0xff, 0x8b, 0x2c, 0x12, 0xb4, 0x06, 0x01, 0x00, 0x00,
206 }
201 0x25, 0x2d, 0x2e, 0x0e, 0xb0, 0xca, 0x82, 0x9c, 0x4a, 0x90, 0x4c, 0x19, 0x4c, 0x5d, 0x99, 0x90,
202 0x00, 0x17, 0x73, 0x6a, 0x51, 0x11, 0x58, 0x25, 0x67, 0x10, 0x88, 0xa9, 0xa4, 0xcd, 0xc5, 0xeb,
203 0x9c, 0x9f, 0x97, 0x9c, 0x58, 0x82, 0x61, 0x30, 0x27, 0x8a, 0xc1, 0x9c, 0x20, 0x83, 0x75, 0xb9,
204 0xb8, 0x61, 0x8a, 0x51, 0xcc, 0xe6, 0xc4, 0x6a, 0xb6, 0x51, 0x0c, 0x17, 0xb3, 0x63, 0x4a, 0x8a,
205 0x90, 0x2a, 0x17, 0x33, 0xd0, 0x39, 0x42, 0x7c, 0x7a, 0x05, 0x49, 0x7a, 0x08, 0x1f, 0x48, 0xf1,
206 0xc0, 0xf9, 0x40, 0xb3, 0x94, 0x18, 0x84, 0xf4, 0xb8, 0xd8, 0x20, 0x86, 0x0b, 0x09, 0x82, 0x64,
207 0x50, 0x5c, 0x25, 0xc5, 0x8f, 0x2c, 0x04, 0x56, 0x9f, 0xc4, 0x06, 0x0e, 0x1a, 0x63, 0x40, 0x00,
208 0x00, 0x00, 0xff, 0xff, 0xdc, 0x37, 0x81, 0x99, 0x2a, 0x01, 0x00, 0x00,
209 }
1919 // The sum response contains the result of the calculation.
2020 message SumReply {
2121 int64 v = 1;
22 string err = 2;
2223 }
2324
2425 // The Concat request contains two parameters.
3031 // The Concat response contains the result of the concatenation.
3132 message ConcatReply {
3233 string v = 1;
34 string err = 2;
3335 }
1818 Concat(ctx context.Context, a, b string) (string, error)
1919 }
2020
21 // Business-domain errors like these may be served in two ways: returned
22 // directly by endpoints, or bundled into the response struct. Both methods can
23 // be made to work, but errors returned directly by endpoints are counted by
24 // middlewares that check errors, like circuit breakers.
25 //
26 // If you don't want that behavior -- and you probably don't -- then it's better
27 // to bundle errors into the response struct.
28
2129 var (
2230 // ErrTwoZeroes is an arbitrary business rule for the Add method.
2331 ErrTwoZeroes = errors.New("can't sum two zeroes")
2432
25 // ErrIntOverflow protects the Add method.
33 // ErrIntOverflow protects the Add method. We've decided that this error
34 // indicates a misbehaving service and should count against e.g. circuit
35 // breakers. So, we return it directly in endpoints, to illustrate the
36 // difference. In a real service, this probably wouldn't be the case.
2637 ErrIntOverflow = errors.New("integer overflow")
2738
2839 // ErrMaxSizeExceeded protects the Concat method.
2940 ErrMaxSizeExceeded = errors.New("result exceeds maximum size")
3041 )
42
43 // These annoying helper functions are required to translate Go error types to
44 // and from strings, which is the type we use in our IDLs to represent errors.
45 // There is special casing to treat empty strings as nil errors.
46
47 func str2err(s string) error {
48 if s == "" {
49 return nil
50 }
51 return errors.New(s)
52 }
53
54 func err2str(err error) string {
55 if err == nil {
56 return ""
57 }
58 return err.Error()
59 }
3160
3261 // NewBasicService returns a naïve, stateless implementation of Service.
3362 func NewBasicService() Service {
00 struct SumReply {
11 1: i64 value
2 2: string err
23 }
34
45 struct ConcatReply {
56 1: string value
7 2: string err
68 }
79
810 service AddService {
1717
1818 // Attributes:
1919 // - Value
20 // - Err
2021 type SumReply struct {
21 Value int64 `thrift:"value,1" json:"value"`
22 Value int64 `thrift:"value,1" json:"value"`
23 Err string `thrift:"err,2" json:"err"`
2224 }
2325
2426 func NewSumReply() *SumReply {
2729
2830 func (p *SumReply) GetValue() int64 {
2931 return p.Value
32 }
33
34 func (p *SumReply) GetErr() string {
35 return p.Err
3036 }
3137 func (p *SumReply) Read(iprot thrift.TProtocol) error {
3238 if _, err := iprot.ReadStructBegin(); err != nil {
4652 if err := p.readField1(iprot); err != nil {
4753 return err
4854 }
55 case 2:
56 if err := p.readField2(iprot); err != nil {
57 return err
58 }
4959 default:
5060 if err := iprot.Skip(fieldTypeId); err != nil {
5161 return err
7080 return nil
7181 }
7282
83 func (p *SumReply) readField2(iprot thrift.TProtocol) error {
84 if v, err := iprot.ReadString(); err != nil {
85 return thrift.PrependError("error reading field 2: ", err)
86 } else {
87 p.Err = v
88 }
89 return nil
90 }
91
7392 func (p *SumReply) Write(oprot thrift.TProtocol) error {
7493 if err := oprot.WriteStructBegin("SumReply"); err != nil {
7594 return thrift.PrependError(fmt.Sprintf("%T write struct begin error: ", p), err)
7796 if err := p.writeField1(oprot); err != nil {
7897 return err
7998 }
99 if err := p.writeField2(oprot); err != nil {
100 return err
101 }
80102 if err := oprot.WriteFieldStop(); err != nil {
81103 return thrift.PrependError("write field stop error: ", err)
82104 }
99121 return err
100122 }
101123
124 func (p *SumReply) writeField2(oprot thrift.TProtocol) (err error) {
125 if err := oprot.WriteFieldBegin("err", thrift.STRING, 2); err != nil {
126 return thrift.PrependError(fmt.Sprintf("%T write field begin error 2:err: ", p), err)
127 }
128 if err := oprot.WriteString(string(p.Err)); err != nil {
129 return thrift.PrependError(fmt.Sprintf("%T.err (2) field write error: ", p), err)
130 }
131 if err := oprot.WriteFieldEnd(); err != nil {
132 return thrift.PrependError(fmt.Sprintf("%T write field end error 2:err: ", p), err)
133 }
134 return err
135 }
136
102137 func (p *SumReply) String() string {
103138 if p == nil {
104139 return "<nil>"
108143
109144 // Attributes:
110145 // - Value
146 // - Err
111147 type ConcatReply struct {
112148 Value string `thrift:"value,1" json:"value"`
149 Err string `thrift:"err,2" json:"err"`
113150 }
114151
115152 func NewConcatReply() *ConcatReply {
118155
119156 func (p *ConcatReply) GetValue() string {
120157 return p.Value
158 }
159
160 func (p *ConcatReply) GetErr() string {
161 return p.Err
121162 }
122163 func (p *ConcatReply) Read(iprot thrift.TProtocol) error {
123164 if _, err := iprot.ReadStructBegin(); err != nil {
137178 if err := p.readField1(iprot); err != nil {
138179 return err
139180 }
181 case 2:
182 if err := p.readField2(iprot); err != nil {
183 return err
184 }
140185 default:
141186 if err := iprot.Skip(fieldTypeId); err != nil {
142187 return err
161206 return nil
162207 }
163208
209 func (p *ConcatReply) readField2(iprot thrift.TProtocol) error {
210 if v, err := iprot.ReadString(); err != nil {
211 return thrift.PrependError("error reading field 2: ", err)
212 } else {
213 p.Err = v
214 }
215 return nil
216 }
217
164218 func (p *ConcatReply) Write(oprot thrift.TProtocol) error {
165219 if err := oprot.WriteStructBegin("ConcatReply"); err != nil {
166220 return thrift.PrependError(fmt.Sprintf("%T write struct begin error: ", p), err)
168222 if err := p.writeField1(oprot); err != nil {
169223 return err
170224 }
225 if err := p.writeField2(oprot); err != nil {
226 return err
227 }
171228 if err := oprot.WriteFieldStop(); err != nil {
172229 return thrift.PrependError("write field stop error: ", err)
173230 }
190247 return err
191248 }
192249
250 func (p *ConcatReply) writeField2(oprot thrift.TProtocol) (err error) {
251 if err := oprot.WriteFieldBegin("err", thrift.STRING, 2); err != nil {
252 return thrift.PrependError(fmt.Sprintf("%T write field begin error 2:err: ", p), err)
253 }
254 if err := oprot.WriteString(string(p.Err)); err != nil {
255 return thrift.PrependError(fmt.Sprintf("%T.err (2) field write error: ", p), err)
256 }
257 if err := oprot.WriteFieldEnd(); err != nil {
258 return thrift.PrependError(fmt.Sprintf("%T write field end error 2:err: ", p), err)
259 }
260 return err
261 }
262
193263 func (p *ConcatReply) String() string {
194264 if p == nil {
195265 return "<nil>"
7575 // gRPC sum reply to a user-domain sum response. Primarily useful in a client.
7676 func DecodeGRPCSumResponse(_ context.Context, grpcReply interface{}) (interface{}, error) {
7777 reply := grpcReply.(*pb.SumReply)
78 return sumResponse{V: int(reply.V)}, nil
78 return sumResponse{V: int(reply.V), Err: str2err(reply.Err)}, nil
7979 }
8080
8181 // DecodeGRPCConcatResponse is a transport/grpc.DecodeResponseFunc that converts
8383 // client.
8484 func DecodeGRPCConcatResponse(_ context.Context, grpcReply interface{}) (interface{}, error) {
8585 reply := grpcReply.(*pb.ConcatReply)
86 return concatResponse{V: reply.V}, nil
86 return concatResponse{V: reply.V, Err: str2err(reply.Err)}, nil
8787 }
8888
8989 // EncodeGRPCSumResponse is a transport/grpc.EncodeResponseFunc that converts a
9090 // user-domain sum response to a gRPC sum reply. Primarily useful in a server.
9191 func EncodeGRPCSumResponse(_ context.Context, response interface{}) (interface{}, error) {
9292 resp := response.(sumResponse)
93 return &pb.SumReply{V: int64(resp.V)}, nil
93 return &pb.SumReply{V: int64(resp.V), Err: err2str(resp.Err)}, nil
9494 }
9595
9696 // EncodeGRPCConcatResponse is a transport/grpc.EncodeResponseFunc that converts
9898 // server.
9999 func EncodeGRPCConcatResponse(_ context.Context, response interface{}) (interface{}, error) {
100100 resp := response.(concatResponse)
101 return &pb.ConcatReply{V: resp.V}, nil
101 return &pb.ConcatReply{V: resp.V, Err: err2str(resp.Err)}, nil
102102 }
103103
104104 // EncodeGRPCSumRequest is a transport/grpc.EncodeRequestFunc that converts a
3434 return nil, err
3535 }
3636 resp := response.(sumResponse)
37 return &thriftadd.SumReply{Value: int64(resp.V)}, nil
37 return &thriftadd.SumReply{Value: int64(resp.V), Err: err2str(resp.Err)}, nil
3838 }
3939
4040 func (s *thriftServer) Concat(a string, b string) (*thriftadd.ConcatReply, error) {
4444 return nil, err
4545 }
4646 resp := response.(concatResponse)
47 return &thriftadd.ConcatReply{Value: resp.V}, nil
47 return &thriftadd.ConcatReply{Value: resp.V, Err: err2str(resp.Err)}, nil
4848 }
4949
5050 // MakeThriftSumEndpoint returns an endpoint that invokes the passed Thrift client.
5353 return func(ctx context.Context, request interface{}) (interface{}, error) {
5454 req := request.(sumRequest)
5555 reply, err := client.Sum(int64(req.A), int64(req.B))
56 if err != nil {
57 return nil, err
56 if err == ErrIntOverflow {
57 return nil, err // special case; see comment on ErrIntOverflow
5858 }
59 return sumResponse{V: int(reply.Value)}, nil
59 return sumResponse{V: int(reply.Value), Err: err}, nil
6060 }
6161 }
6262
6767 return func(ctx context.Context, request interface{}) (interface{}, error) {
6868 req := request.(concatRequest)
6969 reply, err := client.Concat(req.A, req.B)
70 if err != nil {
71 return nil, err
72 }
73 return concatResponse{V: reply.Value}, nil
70 return concatResponse{V: reply.Value, Err: err}, nil
7471 }
7572 }