From 27b1f1431d8e1bc475537d209be6e498c45ab9f6 Mon Sep 17 00:00:00 2001 From: Peter Bourgon Date: Sun, 16 Jul 2017 23:25:24 -0700 Subject: [PATCH 1/9] examples/addsvc2: copy over, incl. gRPC and Thrift --- examples/addsvc2/cmd/addsvc/addsvc.go | 212 +++++ examples/addsvc2/cmd/addsvc/pact_test.go | 55 ++ examples/addsvc2/cmd/addsvc/wiring_test.go | 40 + examples/addsvc2/pb/addsvc.pb.go | 270 ++++++ examples/addsvc2/pb/addsvc.proto | 36 + examples/addsvc2/pb/compile.sh | 14 + examples/addsvc2/pkg/endpoint/middleware.go | 43 + examples/addsvc2/pkg/endpoint/set.go | 106 +++ examples/addsvc2/pkg/service/middleware.go | 69 ++ examples/addsvc2/pkg/service/service.go | 71 ++ examples/addsvc2/pkg/transport/grpc.go | 136 +++ examples/addsvc2/pkg/transport/http.go | 137 +++ examples/addsvc2/pkg/transport/thrift.go | 67 ++ examples/addsvc2/thrift/addsvc.thrift | 14 + examples/addsvc2/thrift/compile.sh | 5 + .../add_service-remote/add_service-remote.go | 157 ++++ .../thrift/gen-go/addsvc/addservice.go | 807 ++++++++++++++++++ .../addsvc2/thrift/gen-go/addsvc/constants.go | 18 + .../addsvc2/thrift/gen-go/addsvc/ttypes.go | 269 ++++++ 19 files changed, 2526 insertions(+) create mode 100644 examples/addsvc2/cmd/addsvc/addsvc.go create mode 100644 examples/addsvc2/cmd/addsvc/pact_test.go create mode 100644 examples/addsvc2/cmd/addsvc/wiring_test.go create mode 100644 examples/addsvc2/pb/addsvc.pb.go create mode 100644 examples/addsvc2/pb/addsvc.proto create mode 100755 examples/addsvc2/pb/compile.sh create mode 100644 examples/addsvc2/pkg/endpoint/middleware.go create mode 100644 examples/addsvc2/pkg/endpoint/set.go create mode 100644 examples/addsvc2/pkg/service/middleware.go create mode 100644 examples/addsvc2/pkg/service/service.go create mode 100644 examples/addsvc2/pkg/transport/grpc.go create mode 100644 examples/addsvc2/pkg/transport/http.go create mode 100644 examples/addsvc2/pkg/transport/thrift.go create mode 100644 examples/addsvc2/thrift/addsvc.thrift create mode 100755 examples/addsvc2/thrift/compile.sh create mode 100755 examples/addsvc2/thrift/gen-go/addsvc/add_service-remote/add_service-remote.go create mode 100644 examples/addsvc2/thrift/gen-go/addsvc/addservice.go create mode 100644 examples/addsvc2/thrift/gen-go/addsvc/constants.go create mode 100644 examples/addsvc2/thrift/gen-go/addsvc/ttypes.go diff --git a/examples/addsvc2/cmd/addsvc/addsvc.go b/examples/addsvc2/cmd/addsvc/addsvc.go new file mode 100644 index 000000000..8f8f2d3ba --- /dev/null +++ b/examples/addsvc2/cmd/addsvc/addsvc.go @@ -0,0 +1,212 @@ +package main + +import ( + "context" + "flag" + "fmt" + "net" + "net/http" + "os" + "os/signal" + "syscall" + + "github.com/apache/thrift/lib/go/thrift" + "github.com/oklog/oklog/pkg/group" + stdopentracing "github.com/opentracing/opentracing-go" + zipkin "github.com/openzipkin/zipkin-go-opentracing" + stdprometheus "github.com/prometheus/client_golang/prometheus" + "google.golang.org/grpc" + + "github.com/go-kit/kit/log" + "github.com/go-kit/kit/metrics" + "github.com/go-kit/kit/metrics/prometheus" + + addpb "github.com/go-kit/kit/examples/addsvc2/pb" + addendpoint "github.com/go-kit/kit/examples/addsvc2/pkg/endpoint" + addservice "github.com/go-kit/kit/examples/addsvc2/pkg/service" + addtransport "github.com/go-kit/kit/examples/addsvc2/pkg/transport" + addthrift "github.com/go-kit/kit/examples/addsvc2/thrift/gen-go/addsvc" +) + +func main() { + var ( + debugAddr = flag.String("debug.addr", ":8080", "Debug and metrics listen address") + httpAddr = flag.String("http-addr", ":8081", "HTTP listen address") + grpcAddr = flag.String("grpc-addr", ":8082", "gRPC listen address") + thriftAddr = flag.String("thrift-addr", ":8082", "Thrift listen address") + thriftProtocol = flag.String("thrift.protocol", "binary", "binary, compact, json, simplejson") + thriftBufferSize = flag.Int("thrift.buffer.size", 0, "0 for unbuffered") + thriftFramed = flag.Bool("thrift.framed", false, "true to enable framing") + zipkinURL = flag.String("zipkin-url", "", "Zipkin collector URL e.g. http://localhost:9411/api/v1/spans") + ) + flag.Parse() + + var logger log.Logger + { + logger = log.NewLogfmtLogger(os.Stderr) + logger = log.With(logger, "ts", log.DefaultTimestampUTC) + logger = log.With(logger, "caller", log.DefaultCaller) + } + + var tracer stdopentracing.Tracer + { + if *zipkinURL != "" { + logger.Log("zipkin", *zipkinURL) + collector, err := zipkin.NewHTTPCollector(*zipkinURL) + if err != nil { + logger.Log("err", err) + os.Exit(1) + } + defer collector.Close() + var ( + debug = false + hostPort = "localhost:80" + serviceName = "addsvc" + ) + tracer, err = zipkin.NewTracer(zipkin.NewRecorder( + collector, debug, hostPort, serviceName, + )) + if err != nil { + logger.Log("err", err) + os.Exit(1) + } + } else { + tracer = stdopentracing.GlobalTracer() // no-op + } + } + + // Our metrics are dependencies, here we create them. + var ints, chars metrics.Counter + { + // Business-level metrics. + ints = prometheus.NewCounterFrom(stdprometheus.CounterOpts{ + Namespace: "example", + Subsystem: "addsvc", + Name: "integers_summed", + Help: "Total count of integers summed via the Sum method.", + }, []string{}) + chars = prometheus.NewCounterFrom(stdprometheus.CounterOpts{ + Namespace: "example", + Subsystem: "addsvc", + Name: "characters_concatenated", + Help: "Total count of characters concatenated via the Concat method.", + }, []string{}) + } + var duration metrics.Histogram + { + // Endpoint-level metrics. + duration = prometheus.NewSummaryFrom(stdprometheus.SummaryOpts{ + Namespace: "example", + Subsystem: "addsvc", + Name: "request_duration_seconds", + Help: "Request duration in seconds.", + }, []string{"method", "success"}) + } + + var ( + service = addservice.New(logger, ints, chars) + endpoints = addendpoint.New(service, logger, duration, tracer) + httpHandler = addtransport.NewHTTPHandler(context.Background(), endpoints, logger, tracer) + grpcServer = addtransport.MakeGRPCServer(endpoints, tracer, logger) + thriftHandler = addtransport.MakeThriftHandler(context.Background(), endpoints) + ) + + var g group.Group + { + debugListener, err := net.Listen("tcp", *debugAddr) + if err != nil { + logger.Log("transport", "debug/HTTP", "during", "Listen", "err", err) + os.Exit(1) + } + g.Add(func() error { + logger.Log("transport", "debug/HTTP", "addr", *debugAddr) + return http.Serve(debugListener, http.DefaultServeMux) + }, func(error) { + debugListener.Close() + }) + } + { + httpListener, err := net.Listen("tcp", *httpAddr) + if err != nil { + logger.Log("transport", "HTTP", "during", "Listen", "err", err) + os.Exit(1) + } + g.Add(func() error { + logger.Log("transport", "HTTP", "addr", *httpAddr) + return http.Serve(httpListener, httpHandler) + }, func(error) { + httpListener.Close() + }) + } + { + grpcListener, err := net.Listen("tcp", *grpcAddr) + if err != nil { + logger.Log("transport", "gRPC", "during", "Listen", "err", err) + os.Exit(1) + } + g.Add(func() error { + logger.Log("transport", "gRPC", "addr", *grpcAddr) + baseServer := grpc.NewServer() + addpb.RegisterAddServer(baseServer, grpcServer) + return baseServer.Serve(grpcListener) + }, func(error) { + grpcListener.Close() + }) + } + { + thriftSocket, err := thrift.NewTServerSocket(*thriftAddr) + if err != nil { + logger.Log("transport", "Thrift", "during", "Listen", "err", err) + os.Exit(1) + } + g.Add(func() error { + logger.Log("transport", "Thrift", "addr", *thriftAddr) + var protocolFactory thrift.TProtocolFactory + switch *thriftProtocol { + case "binary": + protocolFactory = thrift.NewTBinaryProtocolFactoryDefault() + case "compact": + protocolFactory = thrift.NewTCompactProtocolFactory() + case "json": + protocolFactory = thrift.NewTJSONProtocolFactory() + case "simplejson": + protocolFactory = thrift.NewTSimpleJSONProtocolFactory() + default: + return fmt.Errorf("invalid Thrift protocol %q", *thriftProtocol) + } + var transportFactory thrift.TTransportFactory + if *thriftBufferSize > 0 { + transportFactory = thrift.NewTBufferedTransportFactory(*thriftBufferSize) + } else { + transportFactory = thrift.NewTTransportFactory() + } + if *thriftFramed { + transportFactory = thrift.NewTFramedTransportFactory(transportFactory) + } + return thrift.NewTSimpleServer4( + addthrift.NewAddServiceProcessor(thriftHandler), + thriftSocket, + transportFactory, + protocolFactory, + ).Serve() + }, func(error) { + thriftSocket.Close() + }) + } + { + cancelInterrupt := make(chan struct{}) + g.Add(func() error { + c := make(chan os.Signal, 1) + signal.Notify(c, syscall.SIGINT, syscall.SIGTERM) + select { + case sig := <-c: + return fmt.Errorf("received signal %s", sig) + case <-cancelInterrupt: + return nil + } + }, func(error) { + close(cancelInterrupt) + }) + } + logger.Log("exit", g.Run()) +} diff --git a/examples/addsvc2/cmd/addsvc/pact_test.go b/examples/addsvc2/cmd/addsvc/pact_test.go new file mode 100644 index 000000000..2c709b58b --- /dev/null +++ b/examples/addsvc2/cmd/addsvc/pact_test.go @@ -0,0 +1,55 @@ +package main + +import ( + "fmt" + "net/http" + "os" + "strings" + "testing" + + "github.com/pact-foundation/pact-go/dsl" +) + +func TestPactStringsvcUppercase(t *testing.T) { + if os.Getenv("WRITE_PACTS") == "" { + t.Skip("skipping Pact contracts; set WRITE_PACTS environment variable to enable") + } + + pact := dsl.Pact{ + Port: 6666, + Consumer: "addsvc", + Provider: "stringsvc", + } + defer pact.Teardown() + + pact.AddInteraction(). + UponReceiving("stringsvc uppercase"). + WithRequest(dsl.Request{ + Headers: map[string]string{"Content-Type": "application/json; charset=utf-8"}, + Method: "POST", + Path: "/uppercase", + Body: `{"s":"foo"}`, + }). + WillRespondWith(dsl.Response{ + Status: 200, + Headers: map[string]string{"Content-Type": "application/json; charset=utf-8"}, + Body: `{"v":"FOO"}`, + }) + + if err := pact.Verify(func() error { + u := fmt.Sprintf("http://localhost:%d/uppercase", pact.Server.Port) + req, err := http.NewRequest("POST", u, strings.NewReader(`{"s":"foo"}`)) + if err != nil { + return err + } + req.Header.Set("Content-Type", "application/json; charset=utf-8") + if _, err = http.DefaultClient.Do(req); err != nil { + return err + } + return nil + }); err != nil { + t.Fatal(err) + } + + pact.WritePact() +} diff --git a/examples/addsvc2/cmd/addsvc/wiring_test.go b/examples/addsvc2/cmd/addsvc/wiring_test.go new file mode 100644 index 000000000..e2133f4cb --- /dev/null +++ b/examples/addsvc2/cmd/addsvc/wiring_test.go @@ -0,0 +1,40 @@ +package main + +import ( + "context" + "io/ioutil" + "net/http" + "net/http/httptest" + "strings" + "testing" + + "github.com/go-kit/kit/log" + "github.com/go-kit/kit/metrics/discard" + "github.com/opentracing/opentracing-go" + + addendpoint "github.com/go-kit/kit/examples/addsvc2/pkg/endpoint" + addservice "github.com/go-kit/kit/examples/addsvc2/pkg/service" + addtransport "github.com/go-kit/kit/examples/addsvc2/pkg/transport" +) + +func TestHTTP(t *testing.T) { + svc := addservice.New(log.NewNopLogger(), discard.NewCounter(), discard.NewCounter()) + eps := addendpoint.New(svc, log.NewNopLogger(), discard.NewHistogram(), opentracing.GlobalTracer()) + mux := addtransport.NewHTTPHandler(context.Background(), eps, log.NewNopLogger(), opentracing.GlobalTracer()) + srv := httptest.NewServer(mux) + defer srv.Close() + + for _, testcase := range []struct { + method, url, body, want string + }{ + {"GET", srv.URL + "/concat", `{"a":"1","b":"2"}`, `{"v":"12"}`}, + {"GET", srv.URL + "/sum", `{"a":1,"b":2}`, `{"v":3}`}, + } { + req, _ := http.NewRequest(testcase.method, testcase.url, strings.NewReader(testcase.body)) + resp, _ := http.DefaultClient.Do(req) + body, _ := ioutil.ReadAll(resp.Body) + if want, have := testcase.want, strings.TrimSpace(string(body)); want != have { + t.Errorf("%s %s %s: want %q, have %q", testcase.method, testcase.url, testcase.body, want, have) + } + } +} diff --git a/examples/addsvc2/pb/addsvc.pb.go b/examples/addsvc2/pb/addsvc.pb.go new file mode 100644 index 000000000..781b50b75 --- /dev/null +++ b/examples/addsvc2/pb/addsvc.pb.go @@ -0,0 +1,270 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// source: addsvc.proto + +/* +Package pb is a generated protocol buffer package. + +It is generated from these files: + addsvc.proto + +It has these top-level messages: + SumRequest + SumReply + ConcatRequest + ConcatReply +*/ +package pb + +import proto "github.com/golang/protobuf/proto" +import fmt "fmt" +import math "math" + +import ( + context "golang.org/x/net/context" + grpc "google.golang.org/grpc" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package + +// The sum request contains two parameters. +type SumRequest struct { + A int64 `protobuf:"varint,1,opt,name=a" json:"a,omitempty"` + B int64 `protobuf:"varint,2,opt,name=b" json:"b,omitempty"` +} + +func (m *SumRequest) Reset() { *m = SumRequest{} } +func (m *SumRequest) String() string { return proto.CompactTextString(m) } +func (*SumRequest) ProtoMessage() {} +func (*SumRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} } + +func (m *SumRequest) GetA() int64 { + if m != nil { + return m.A + } + return 0 +} + +func (m *SumRequest) GetB() int64 { + if m != nil { + return m.B + } + return 0 +} + +// The sum response contains the result of the calculation. +type SumReply struct { + V int64 `protobuf:"varint,1,opt,name=v" json:"v,omitempty"` + Err string `protobuf:"bytes,2,opt,name=err" json:"err,omitempty"` +} + +func (m *SumReply) Reset() { *m = SumReply{} } +func (m *SumReply) String() string { return proto.CompactTextString(m) } +func (*SumReply) ProtoMessage() {} +func (*SumReply) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} } + +func (m *SumReply) GetV() int64 { + if m != nil { + return m.V + } + return 0 +} + +func (m *SumReply) GetErr() string { + if m != nil { + return m.Err + } + return "" +} + +// The Concat request contains two parameters. +type ConcatRequest struct { + A string `protobuf:"bytes,1,opt,name=a" json:"a,omitempty"` + B string `protobuf:"bytes,2,opt,name=b" json:"b,omitempty"` +} + +func (m *ConcatRequest) Reset() { *m = ConcatRequest{} } +func (m *ConcatRequest) String() string { return proto.CompactTextString(m) } +func (*ConcatRequest) ProtoMessage() {} +func (*ConcatRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2} } + +func (m *ConcatRequest) GetA() string { + if m != nil { + return m.A + } + return "" +} + +func (m *ConcatRequest) GetB() string { + if m != nil { + return m.B + } + return "" +} + +// The Concat response contains the result of the concatenation. +type ConcatReply struct { + V string `protobuf:"bytes,1,opt,name=v" json:"v,omitempty"` + Err string `protobuf:"bytes,2,opt,name=err" json:"err,omitempty"` +} + +func (m *ConcatReply) Reset() { *m = ConcatReply{} } +func (m *ConcatReply) String() string { return proto.CompactTextString(m) } +func (*ConcatReply) ProtoMessage() {} +func (*ConcatReply) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{3} } + +func (m *ConcatReply) GetV() string { + if m != nil { + return m.V + } + return "" +} + +func (m *ConcatReply) GetErr() string { + if m != nil { + return m.Err + } + return "" +} + +func init() { + proto.RegisterType((*SumRequest)(nil), "pb.SumRequest") + proto.RegisterType((*SumReply)(nil), "pb.SumReply") + proto.RegisterType((*ConcatRequest)(nil), "pb.ConcatRequest") + proto.RegisterType((*ConcatReply)(nil), "pb.ConcatReply") +} + +// Reference imports to suppress errors if they are not otherwise used. +var _ context.Context +var _ grpc.ClientConn + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +const _ = grpc.SupportPackageIsVersion4 + +// Client API for Add service + +type AddClient interface { + // Sums two integers. + Sum(ctx context.Context, in *SumRequest, opts ...grpc.CallOption) (*SumReply, error) + // Concatenates two strings + Concat(ctx context.Context, in *ConcatRequest, opts ...grpc.CallOption) (*ConcatReply, error) +} + +type addClient struct { + cc *grpc.ClientConn +} + +func NewAddClient(cc *grpc.ClientConn) AddClient { + return &addClient{cc} +} + +func (c *addClient) Sum(ctx context.Context, in *SumRequest, opts ...grpc.CallOption) (*SumReply, error) { + out := new(SumReply) + err := grpc.Invoke(ctx, "/pb.Add/Sum", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *addClient) Concat(ctx context.Context, in *ConcatRequest, opts ...grpc.CallOption) (*ConcatReply, error) { + out := new(ConcatReply) + err := grpc.Invoke(ctx, "/pb.Add/Concat", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// Server API for Add service + +type AddServer interface { + // Sums two integers. + Sum(context.Context, *SumRequest) (*SumReply, error) + // Concatenates two strings + Concat(context.Context, *ConcatRequest) (*ConcatReply, error) +} + +func RegisterAddServer(s *grpc.Server, srv AddServer) { + s.RegisterService(&_Add_serviceDesc, srv) +} + +func _Add_Sum_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(SumRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(AddServer).Sum(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/pb.Add/Sum", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(AddServer).Sum(ctx, req.(*SumRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Add_Concat_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(ConcatRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(AddServer).Concat(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/pb.Add/Concat", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(AddServer).Concat(ctx, req.(*ConcatRequest)) + } + return interceptor(ctx, in, info, handler) +} + +var _Add_serviceDesc = grpc.ServiceDesc{ + ServiceName: "pb.Add", + HandlerType: (*AddServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "Sum", + Handler: _Add_Sum_Handler, + }, + { + MethodName: "Concat", + Handler: _Add_Concat_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "addsvc.proto", +} + +func init() { proto.RegisterFile("addsvc.proto", fileDescriptor0) } + +var fileDescriptor0 = []byte{ + // 189 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xe2, 0x49, 0x4c, 0x49, 0x29, + 0x2e, 0x4b, 0xd6, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x62, 0x2a, 0x48, 0x52, 0xd2, 0xe0, 0xe2, + 0x0a, 0x2e, 0xcd, 0x0d, 0x4a, 0x2d, 0x2c, 0x4d, 0x2d, 0x2e, 0x11, 0xe2, 0xe1, 0x62, 0x4c, 0x94, + 0x60, 0x54, 0x60, 0xd4, 0x60, 0x0e, 0x62, 0x4c, 0x04, 0xf1, 0x92, 0x24, 0x98, 0x20, 0xbc, 0x24, + 0x25, 0x2d, 0x2e, 0x0e, 0xb0, 0xca, 0x82, 0x9c, 0x4a, 0x90, 0x4c, 0x19, 0x4c, 0x5d, 0x99, 0x90, + 0x00, 0x17, 0x73, 0x6a, 0x51, 0x11, 0x58, 0x25, 0x67, 0x10, 0x88, 0xa9, 0xa4, 0xcd, 0xc5, 0xeb, + 0x9c, 0x9f, 0x97, 0x9c, 0x58, 0x82, 0x61, 0x30, 0x27, 0x8a, 0xc1, 0x9c, 0x20, 0x83, 0x75, 0xb9, + 0xb8, 0x61, 0x8a, 0x51, 0xcc, 0xe6, 0xc4, 0x6a, 0xb6, 0x51, 0x0c, 0x17, 0xb3, 0x63, 0x4a, 0x8a, + 0x90, 0x2a, 0x17, 0x73, 0x70, 0x69, 0xae, 0x10, 0x9f, 0x5e, 0x41, 0x92, 0x1e, 0xc2, 0x07, 0x52, + 0x3c, 0x70, 0x7e, 0x41, 0x4e, 0xa5, 0x12, 0x83, 0x90, 0x1e, 0x17, 0x1b, 0xc4, 0x70, 0x21, 0x41, + 0x90, 0x0c, 0x8a, 0xab, 0xa4, 0xf8, 0x91, 0x85, 0xc0, 0xea, 0x93, 0xd8, 0xc0, 0x41, 0x63, 0x0c, + 0x08, 0x00, 0x00, 0xff, 0xff, 0xdc, 0x37, 0x81, 0x99, 0x2a, 0x01, 0x00, 0x00, +} diff --git a/examples/addsvc2/pb/addsvc.proto b/examples/addsvc2/pb/addsvc.proto new file mode 100644 index 000000000..cf61532f3 --- /dev/null +++ b/examples/addsvc2/pb/addsvc.proto @@ -0,0 +1,36 @@ +syntax = "proto3"; + +package pb; + +// The Add service definition. +service Add { + // Sums two integers. + rpc Sum (SumRequest) returns (SumReply) {} + + // Concatenates two strings + rpc Concat (ConcatRequest) returns (ConcatReply) {} +} + +// The sum request contains two parameters. +message SumRequest { + int64 a = 1; + int64 b = 2; +} + +// The sum response contains the result of the calculation. +message SumReply { + int64 v = 1; + string err = 2; +} + +// The Concat request contains two parameters. +message ConcatRequest { + string a = 1; + string b = 2; +} + +// The Concat response contains the result of the concatenation. +message ConcatReply { + string v = 1; + string err = 2; +} diff --git a/examples/addsvc2/pb/compile.sh b/examples/addsvc2/pb/compile.sh new file mode 100755 index 000000000..c0268442a --- /dev/null +++ b/examples/addsvc2/pb/compile.sh @@ -0,0 +1,14 @@ +#!/usr/bin/env sh + +# Install proto3 from source +# brew install autoconf automake libtool +# git clone https://github.com/google/protobuf +# ./autogen.sh ; ./configure ; make ; make install +# +# Update protoc Go bindings via +# go get -u github.com/golang/protobuf/{proto,protoc-gen-go} +# +# See also +# https://github.com/grpc/grpc-go/tree/master/examples + +protoc addsvc.proto --go_out=plugins=grpc:. diff --git a/examples/addsvc2/pkg/endpoint/middleware.go b/examples/addsvc2/pkg/endpoint/middleware.go new file mode 100644 index 000000000..d02bfbefb --- /dev/null +++ b/examples/addsvc2/pkg/endpoint/middleware.go @@ -0,0 +1,43 @@ +package endpoint + +import ( + "context" + "fmt" + "time" + + "github.com/go-kit/kit/endpoint" + "github.com/go-kit/kit/log" + "github.com/go-kit/kit/metrics" +) + +// InstrumentingMiddleware returns an endpoint middleware that records +// the duration of each invocation to the passed histogram. The middleware adds +// a single field: "success", which is "true" if no error is returned, and +// "false" otherwise. +func InstrumentingMiddleware(duration metrics.Histogram) endpoint.Middleware { + return func(next endpoint.Endpoint) endpoint.Endpoint { + return func(ctx context.Context, request interface{}) (response interface{}, err error) { + + defer func(begin time.Time) { + duration.With("success", fmt.Sprint(err == nil)).Observe(time.Since(begin).Seconds()) + }(time.Now()) + return next(ctx, request) + + } + } +} + +// LoggingMiddleware returns an endpoint middleware that logs the +// duration of each invocation, and the resulting error, if any. +func LoggingMiddleware(logger log.Logger) endpoint.Middleware { + return func(next endpoint.Endpoint) endpoint.Endpoint { + return func(ctx context.Context, request interface{}) (response interface{}, err error) { + + defer func(begin time.Time) { + logger.Log("transport_error", err, "took", time.Since(begin)) + }(time.Now()) + return next(ctx, request) + + } + } +} diff --git a/examples/addsvc2/pkg/endpoint/set.go b/examples/addsvc2/pkg/endpoint/set.go new file mode 100644 index 000000000..6b0630e14 --- /dev/null +++ b/examples/addsvc2/pkg/endpoint/set.go @@ -0,0 +1,106 @@ +package endpoint + +import ( + "context" + + rl "github.com/juju/ratelimit" + stdopentracing "github.com/opentracing/opentracing-go" + "github.com/sony/gobreaker" + + "github.com/go-kit/kit/circuitbreaker" + "github.com/go-kit/kit/endpoint" + "github.com/go-kit/kit/log" + "github.com/go-kit/kit/metrics" + "github.com/go-kit/kit/ratelimit" + "github.com/go-kit/kit/tracing/opentracing" + + "github.com/go-kit/kit/examples/addsvc2/pkg/service" +) + +// Set collects all of the endpoints that compose an add service. It's meant to +// be used as a helper struct, to collect all of the endpoints into a single +// parameter. +type Set struct { + SumEndpoint endpoint.Endpoint + ConcatEndpoint endpoint.Endpoint +} + +// New returns a Set that wraps the provided server, and wires in all of the +// expected endpoint middlewares via the various parameters. +func New(svc service.Service, logger log.Logger, duration metrics.Histogram, trace stdopentracing.Tracer) Set { + var sumEndpoint endpoint.Endpoint + { + sumEndpoint = MakeSumEndpoint(svc) + sumEndpoint = ratelimit.NewTokenBucketLimiter(rl.NewBucketWithRate(1, 1))(sumEndpoint) + sumEndpoint = circuitbreaker.Gobreaker(gobreaker.NewCircuitBreaker(gobreaker.Settings{}))(sumEndpoint) + sumEndpoint = opentracing.TraceServer(trace, "Sum")(sumEndpoint) + sumEndpoint = LoggingMiddleware(log.With(logger, "method", "Sum"))(sumEndpoint) + sumEndpoint = InstrumentingMiddleware(duration.With("method", "Sum"))(sumEndpoint) + } + var concatEndpoint endpoint.Endpoint + { + concatEndpoint = MakeConcatEndpoint(svc) + concatEndpoint = ratelimit.NewTokenBucketLimiter(rl.NewBucketWithRate(100, 100))(concatEndpoint) + concatEndpoint = circuitbreaker.Gobreaker(gobreaker.NewCircuitBreaker(gobreaker.Settings{}))(concatEndpoint) + concatEndpoint = opentracing.TraceServer(trace, "Concat")(concatEndpoint) + concatEndpoint = LoggingMiddleware(log.With(logger, "method", "Concat"))(concatEndpoint) + concatEndpoint = InstrumentingMiddleware(duration.With("method", "Concat"))(concatEndpoint) + } + return Set{ + SumEndpoint: sumEndpoint, + ConcatEndpoint: concatEndpoint, + } +} + +// MakeSumEndpoint constructs a Sum endpoint wrapping the service. +func MakeSumEndpoint(s service.Service) endpoint.Endpoint { + return func(ctx context.Context, request interface{}) (response interface{}, err error) { + req := request.(SumRequest) + v, err := s.Sum(ctx, req.A, req.B) + return SumResponse{V: v, Err: err}, nil + } +} + +// MakeConcatEndpoint constructs a Concat endpoint wrapping the service. +func MakeConcatEndpoint(s service.Service) endpoint.Endpoint { + return func(ctx context.Context, request interface{}) (response interface{}, err error) { + req := request.(ConcatRequest) + v, err := s.Concat(ctx, req.A, req.B) + return ConcatResponse{V: v, Err: err}, nil + } +} + +// Failer is an interface that should be implemented by response types. +// Response encoders can check if responses are Failer, and if so if they've +// failed, and if so encode them using a separate write path based on the error. +type Failer interface { + Failed() error +} + +// SumRequest collects the request parameters for the Sum method. +type SumRequest struct { + A, B int +} + +// SumResponse collects the response values for the Sum method. +type SumResponse struct { + V int `json:"v"` + Err error `json:"-"` // should be intercepted by Failed/errorEncoder +} + +// Failed implements Failer. +func (r SumResponse) Failed() error { return r.Err } + +// ConcatRequest collects the request parameters for the Concat method. +type ConcatRequest struct { + A, B string +} + +// ConcatResponse collects the response values for the Concat method. +type ConcatResponse struct { + V string `json:"v"` + Err error `json:"-"` +} + +// Failed implements Failer. +func (r ConcatResponse) Failed() error { return r.Err } diff --git a/examples/addsvc2/pkg/service/middleware.go b/examples/addsvc2/pkg/service/middleware.go new file mode 100644 index 000000000..ba028e776 --- /dev/null +++ b/examples/addsvc2/pkg/service/middleware.go @@ -0,0 +1,69 @@ +package service + +import ( + "context" + + "github.com/go-kit/kit/log" + "github.com/go-kit/kit/metrics" +) + +// Middleware describes a service (as opposed to endpoint) middleware. +type Middleware func(Service) Service + +// LoggingMiddleware takes a logger as a dependency +// and returns a ServiceMiddleware. +func LoggingMiddleware(logger log.Logger) Middleware { + return func(next Service) Service { + return loggingMiddleware{logger, next} + } +} + +type loggingMiddleware struct { + logger log.Logger + next Service +} + +func (mw loggingMiddleware) Sum(ctx context.Context, a, b int) (v int, err error) { + defer func() { + mw.logger.Log("method", "Sum", "a", a, "b", b, "v", v, "err", err) + }() + return mw.next.Sum(ctx, a, b) +} + +func (mw loggingMiddleware) Concat(ctx context.Context, a, b string) (v string, err error) { + defer func() { + mw.logger.Log("method", "Concat", "a", a, "b", b, "v", v, "err", err) + }() + return mw.next.Concat(ctx, a, b) +} + +// InstrumentingMiddleware returns a service middleware that instruments +// the number of integers summed and characters concatenated over the lifetime of +// the service. +func InstrumentingMiddleware(ints, chars metrics.Counter) Middleware { + return func(next Service) Service { + return instrumentingMiddleware{ + ints: ints, + chars: chars, + next: next, + } + } +} + +type instrumentingMiddleware struct { + ints metrics.Counter + chars metrics.Counter + next Service +} + +func (mw instrumentingMiddleware) Sum(ctx context.Context, a, b int) (int, error) { + v, err := mw.next.Sum(ctx, a, b) + mw.ints.Add(float64(v)) + return v, err +} + +func (mw instrumentingMiddleware) Concat(ctx context.Context, a, b string) (string, error) { + v, err := mw.next.Concat(ctx, a, b) + mw.chars.Add(float64(len(v))) + return v, err +} diff --git a/examples/addsvc2/pkg/service/service.go b/examples/addsvc2/pkg/service/service.go new file mode 100644 index 000000000..7612cf2ae --- /dev/null +++ b/examples/addsvc2/pkg/service/service.go @@ -0,0 +1,71 @@ +package service + +import ( + "context" + "errors" + + "github.com/go-kit/kit/log" + "github.com/go-kit/kit/metrics" +) + +// Service describes a service that adds things together. +type Service interface { + Sum(ctx context.Context, a, b int) (int, error) + Concat(ctx context.Context, a, b string) (string, error) +} + +// New returns a basic Service with all of the expected middlewares wired in. +func New(logger log.Logger, ints, chars metrics.Counter) Service { + var svc Service + { + svc = NewBasicService() + svc = LoggingMiddleware(logger)(svc) + svc = InstrumentingMiddleware(ints, chars)(svc) + } + return svc +} + +var ( + // ErrTwoZeroes is an arbitrary business rule for the Add method. + ErrTwoZeroes = errors.New("can't sum two zeroes") + + // ErrIntOverflow protects the Add method. We've decided that this error + // indicates a misbehaving service and should count against e.g. circuit + // breakers. So, we return it directly in endpoints, to illustrate the + // difference. In a real service, this probably wouldn't be the case. + ErrIntOverflow = errors.New("integer overflow") + + // ErrMaxSizeExceeded protects the Concat method. + ErrMaxSizeExceeded = errors.New("result exceeds maximum size") +) + +// NewBasicService returns a naïve, stateless implementation of Service. +func NewBasicService() Service { + return basicService{} +} + +type basicService struct{} + +const ( + intMax = 1<<31 - 1 + intMin = -(intMax + 1) + maxLen = 10 +) + +func (s basicService) Sum(_ context.Context, a, b int) (int, error) { + if a == 0 && b == 0 { + return 0, ErrTwoZeroes + } + if (b > 0 && a > (intMax-b)) || (b < 0 && a < (intMin-b)) { + return 0, ErrIntOverflow + } + return a + b, nil +} + +// Concat implements Service. +func (s basicService) Concat(_ context.Context, a, b string) (string, error) { + if len(a)+len(b) > maxLen { + return "", ErrMaxSizeExceeded + } + return a + b, nil +} diff --git a/examples/addsvc2/pkg/transport/grpc.go b/examples/addsvc2/pkg/transport/grpc.go new file mode 100644 index 000000000..bbbb5925c --- /dev/null +++ b/examples/addsvc2/pkg/transport/grpc.go @@ -0,0 +1,136 @@ +package transport + +import ( + "context" + "errors" + + stdopentracing "github.com/opentracing/opentracing-go" + oldcontext "golang.org/x/net/context" + + "github.com/go-kit/kit/log" + "github.com/go-kit/kit/tracing/opentracing" + grpctransport "github.com/go-kit/kit/transport/grpc" + + "github.com/go-kit/kit/examples/addsvc2/pb" + "github.com/go-kit/kit/examples/addsvc2/pkg/endpoint" +) + +// MakeGRPCServer makes a set of endpoints available as a gRPC AddServer. +func MakeGRPCServer(endpoints endpoint.Set, tracer stdopentracing.Tracer, logger log.Logger) pb.AddServer { + options := []grpctransport.ServerOption{ + grpctransport.ServerErrorLogger(logger), + } + return &grpcServer{ + sum: grpctransport.NewServer( + endpoints.SumEndpoint, + decodeGRPCSumRequest, + encodeGRPCSumResponse, + append(options, grpctransport.ServerBefore(opentracing.FromGRPCRequest(tracer, "Sum", logger)))..., + ), + concat: grpctransport.NewServer( + endpoints.ConcatEndpoint, + decodeGRPCConcatRequest, + encodeGRPCConcatResponse, + append(options, grpctransport.ServerBefore(opentracing.FromGRPCRequest(tracer, "Concat", logger)))..., + ), + } +} + +type grpcServer struct { + sum grpctransport.Handler + concat grpctransport.Handler +} + +func (s *grpcServer) Sum(ctx oldcontext.Context, req *pb.SumRequest) (*pb.SumReply, error) { + _, rep, err := s.sum.ServeGRPC(ctx, req) + if err != nil { + return nil, err + } + return rep.(*pb.SumReply), nil +} + +func (s *grpcServer) Concat(ctx oldcontext.Context, req *pb.ConcatRequest) (*pb.ConcatReply, error) { + _, rep, err := s.concat.ServeGRPC(ctx, req) + if err != nil { + return nil, err + } + return rep.(*pb.ConcatReply), nil +} + +// decodeGRPCSumRequest is a transport/grpc.DecodeRequestFunc that converts a +// gRPC sum request to a user-domain sum request. Primarily useful in a server. +func decodeGRPCSumRequest(_ context.Context, grpcReq interface{}) (interface{}, error) { + req := grpcReq.(*pb.SumRequest) + return endpoint.SumRequest{A: int(req.A), B: int(req.B)}, nil +} + +// decodeGRPCConcatRequest is a transport/grpc.DecodeRequestFunc that converts a +// gRPC concat request to a user-domain concat request. Primarily useful in a +// server. +func decodeGRPCConcatRequest(_ context.Context, grpcReq interface{}) (interface{}, error) { + req := grpcReq.(*pb.ConcatRequest) + return endpoint.ConcatRequest{A: req.A, B: req.B}, nil +} + +// decodeGRPCSumResponse is a transport/grpc.DecodeResponseFunc that converts a +// gRPC sum reply to a user-domain sum response. Primarily useful in a client. +func decodeGRPCSumResponse(_ context.Context, grpcReply interface{}) (interface{}, error) { + reply := grpcReply.(*pb.SumReply) + return endpoint.SumResponse{V: int(reply.V), Err: str2err(reply.Err)}, nil +} + +// decodeGRPCConcatResponse is a transport/grpc.DecodeResponseFunc that converts +// a gRPC concat reply to a user-domain concat response. Primarily useful in a +// client. +func decodeGRPCConcatResponse(_ context.Context, grpcReply interface{}) (interface{}, error) { + reply := grpcReply.(*pb.ConcatReply) + return endpoint.ConcatResponse{V: reply.V, Err: str2err(reply.Err)}, nil +} + +// encodeGRPCSumResponse is a transport/grpc.EncodeResponseFunc that converts a +// user-domain sum response to a gRPC sum reply. Primarily useful in a server. +func encodeGRPCSumResponse(_ context.Context, response interface{}) (interface{}, error) { + resp := response.(endpoint.SumResponse) + return &pb.SumReply{V: int64(resp.V), Err: err2str(resp.Err)}, nil +} + +// encodeGRPCConcatResponse is a transport/grpc.EncodeResponseFunc that converts +// a user-domain concat response to a gRPC concat reply. Primarily useful in a +// server. +func encodeGRPCConcatResponse(_ context.Context, response interface{}) (interface{}, error) { + resp := response.(endpoint.ConcatResponse) + return &pb.ConcatReply{V: resp.V, Err: err2str(resp.Err)}, nil +} + +// encodeGRPCSumRequest is a transport/grpc.EncodeRequestFunc that converts a +// user-domain sum request to a gRPC sum request. Primarily useful in a client. +func encodeGRPCSumRequest(_ context.Context, request interface{}) (interface{}, error) { + req := request.(endpoint.SumRequest) + return &pb.SumRequest{A: int64(req.A), B: int64(req.B)}, nil +} + +// encodeGRPCConcatRequest is a transport/grpc.EncodeRequestFunc that converts a +// user-domain concat request to a gRPC concat request. Primarily useful in a +// client. +func encodeGRPCConcatRequest(_ context.Context, request interface{}) (interface{}, error) { + req := request.(endpoint.ConcatRequest) + return &pb.ConcatRequest{A: req.A, B: req.B}, nil +} + +// These annoying helper functions are required to translate Go error types to +// and from strings, which is the type we use in our IDLs to represent errors. +// There is special casing to treat empty strings as nil errors. + +func str2err(s string) error { + if s == "" { + return nil + } + return errors.New(s) +} + +func err2str(err error) string { + if err == nil { + return "" + } + return err.Error() +} diff --git a/examples/addsvc2/pkg/transport/http.go b/examples/addsvc2/pkg/transport/http.go new file mode 100644 index 000000000..4146b31b3 --- /dev/null +++ b/examples/addsvc2/pkg/transport/http.go @@ -0,0 +1,137 @@ +package transport + +import ( + "bytes" + "context" + "encoding/json" + "errors" + "io/ioutil" + "net/http" + + stdopentracing "github.com/opentracing/opentracing-go" + "github.com/prometheus/client_golang/prometheus/promhttp" + + "github.com/go-kit/kit/log" + "github.com/go-kit/kit/tracing/opentracing" + httptransport "github.com/go-kit/kit/transport/http" + + "github.com/go-kit/kit/examples/addsvc2/pkg/endpoint" + "github.com/go-kit/kit/examples/addsvc2/pkg/service" +) + +// NewHTTPHandler returns an HTTP handler that makes a set of endpoints +// available on predefined paths. +func NewHTTPHandler(ctx context.Context, endpoints endpoint.Set, logger log.Logger, trace stdopentracing.Tracer) http.Handler { + options := []httptransport.ServerOption{ + httptransport.ServerErrorEncoder(errorEncoder), + httptransport.ServerErrorLogger(logger), + } + m := http.NewServeMux() + m.Handle("/sum", httptransport.NewServer( + endpoints.SumEndpoint, + decodeHTTPSumRequest, + encodeHTTPGenericResponse, + append(options, httptransport.ServerBefore(opentracing.FromHTTPRequest(trace, "Sum", logger)))..., + )) + m.Handle("/concat", httptransport.NewServer( + endpoints.ConcatEndpoint, + decodeHTTPConcatRequest, + encodeHTTPGenericResponse, + append(options, httptransport.ServerBefore(opentracing.FromHTTPRequest(trace, "Concat", logger)))..., + )) + m.Handle("/metrics", promhttp.Handler()) + return m +} + +func errorEncoder(_ context.Context, err error, w http.ResponseWriter) { + w.WriteHeader(err2code(err)) + json.NewEncoder(w).Encode(errorWrapper{Error: err.Error()}) +} + +func err2code(err error) int { + switch err { + case service.ErrTwoZeroes, service.ErrMaxSizeExceeded, service.ErrIntOverflow: + return http.StatusBadRequest + } + return http.StatusInternalServerError +} + +func errorDecoder(r *http.Response) error { + var w errorWrapper + if err := json.NewDecoder(r.Body).Decode(&w); err != nil { + return err + } + return errors.New(w.Error) +} + +type errorWrapper struct { + Error string `json:"error"` +} + +// decodeHTTPSumRequest is a transport/http.DecodeRequestFunc that decodes a +// JSON-encoded sum request from the HTTP request body. Primarily useful in a +// server. +func decodeHTTPSumRequest(_ context.Context, r *http.Request) (interface{}, error) { + var req endpoint.SumRequest + err := json.NewDecoder(r.Body).Decode(&req) + return req, err +} + +// decodeHTTPConcatRequest is a transport/http.DecodeRequestFunc that decodes a +// JSON-encoded concat request from the HTTP request body. Primarily useful in a +// server. +func decodeHTTPConcatRequest(_ context.Context, r *http.Request) (interface{}, error) { + var req endpoint.ConcatRequest + err := json.NewDecoder(r.Body).Decode(&req) + return req, err +} + +// decodeHTTPSumResponse is a transport/http.DecodeResponseFunc that decodes a +// JSON-encoded sum response from the HTTP response body. If the response has a +// non-200 status code, we will interpret that as an error and attempt to decode +// the specific error message from the response body. Primarily useful in a +// client. +func decodeHTTPSumResponse(_ context.Context, r *http.Response) (interface{}, error) { + if r.StatusCode != http.StatusOK { + return nil, errors.New(r.Status) + } + var resp endpoint.SumResponse + err := json.NewDecoder(r.Body).Decode(&resp) + return resp, err +} + +// decodeHTTPConcatResponse is a transport/http.DecodeResponseFunc that decodes +// a JSON-encoded concat response from the HTTP response body. If the response +// has a non-200 status code, we will interpret that as an error and attempt to +// decode the specific error message from the response body. Primarily useful in +// a client. +func decodeHTTPConcatResponse(_ context.Context, r *http.Response) (interface{}, error) { + if r.StatusCode != http.StatusOK { + return nil, errors.New(r.Status) + } + var resp endpoint.ConcatResponse + err := json.NewDecoder(r.Body).Decode(&resp) + return resp, err +} + +// encodeHTTPGenericRequest is a transport/http.EncodeRequestFunc that +// JSON-encodes any request to the request body. Primarily useful in a client. +func encodeHTTPGenericRequest(_ context.Context, r *http.Request, request interface{}) error { + var buf bytes.Buffer + if err := json.NewEncoder(&buf).Encode(request); err != nil { + return err + } + r.Body = ioutil.NopCloser(&buf) + return nil +} + +// encodeHTTPGenericResponse is a transport/http.EncodeResponseFunc that encodes +// the response as JSON to the response writer. Primarily useful in a server. +func encodeHTTPGenericResponse(ctx context.Context, w http.ResponseWriter, response interface{}) error { + if f, ok := response.(endpoint.Failer); ok && f.Failed() != nil { + errorEncoder(ctx, f.Failed(), w) + return nil + } + w.Header().Set("Content-Type", "application/json; charset=utf-8") + return json.NewEncoder(w).Encode(response) +} diff --git a/examples/addsvc2/pkg/transport/thrift.go b/examples/addsvc2/pkg/transport/thrift.go new file mode 100644 index 000000000..02beba550 --- /dev/null +++ b/examples/addsvc2/pkg/transport/thrift.go @@ -0,0 +1,67 @@ +package transport + +import ( + "context" + + "github.com/go-kit/kit/endpoint" + addendpoint "github.com/go-kit/kit/examples/addsvc2/pkg/endpoint" + "github.com/go-kit/kit/examples/addsvc2/pkg/service" + thriftadd "github.com/go-kit/kit/examples/addsvc2/thrift/gen-go/addsvc" +) + +// MakeThriftHandler makes a set of endpoints available as a Thrift service. +func MakeThriftHandler(ctx context.Context, endpoints addendpoint.Set) thriftadd.AddService { + return &thriftServer{ + ctx: ctx, + endpoints: endpoints, + } +} + +type thriftServer struct { + ctx context.Context + endpoints addendpoint.Set +} + +func (s *thriftServer) Sum(a int64, b int64) (*thriftadd.SumReply, error) { + request := addendpoint.SumRequest{A: int(a), B: int(b)} + response, err := s.endpoints.SumEndpoint(s.ctx, request) + if err != nil { + return nil, err + } + resp := response.(addendpoint.SumResponse) + return &thriftadd.SumReply{Value: int64(resp.V), Err: err2str(resp.Err)}, nil +} + +func (s *thriftServer) Concat(a string, b string) (*thriftadd.ConcatReply, error) { + request := addendpoint.ConcatRequest{A: a, B: b} + response, err := s.endpoints.ConcatEndpoint(s.ctx, request) + if err != nil { + return nil, err + } + resp := response.(addendpoint.ConcatResponse) + return &thriftadd.ConcatReply{Value: resp.V, Err: err2str(resp.Err)}, nil +} + +// MakeThriftSumEndpoint returns an endpoint that invokes the passed Thrift client. +// Useful only in clients, and only until a proper transport/thrift.Client exists. +func MakeThriftSumEndpoint(client *thriftadd.AddServiceClient) endpoint.Endpoint { + return func(ctx context.Context, request interface{}) (interface{}, error) { + req := request.(addendpoint.SumRequest) + reply, err := client.Sum(int64(req.A), int64(req.B)) + if err == service.ErrIntOverflow { + return nil, err // special case; see comment on ErrIntOverflow + } + return addendpoint.SumResponse{V: int(reply.Value), Err: err}, nil + } +} + +// MakeThriftConcatEndpoint returns an endpoint that invokes the passed Thrift +// client. Useful only in clients, and only until a proper +// transport/thrift.Client exists. +func MakeThriftConcatEndpoint(client *thriftadd.AddServiceClient) endpoint.Endpoint { + return func(ctx context.Context, request interface{}) (interface{}, error) { + req := request.(addendpoint.ConcatRequest) + reply, err := client.Concat(req.A, req.B) + return addendpoint.ConcatResponse{V: reply.Value, Err: err}, nil + } +} diff --git a/examples/addsvc2/thrift/addsvc.thrift b/examples/addsvc2/thrift/addsvc.thrift new file mode 100644 index 000000000..e67ce1b21 --- /dev/null +++ b/examples/addsvc2/thrift/addsvc.thrift @@ -0,0 +1,14 @@ +struct SumReply { + 1: i64 value + 2: string err +} + +struct ConcatReply { + 1: string value + 2: string err +} + +service AddService { + SumReply Sum(1: i64 a, 2: i64 b) + ConcatReply Concat(1: string a, 2: string b) +} diff --git a/examples/addsvc2/thrift/compile.sh b/examples/addsvc2/thrift/compile.sh new file mode 100755 index 000000000..add8ffa25 --- /dev/null +++ b/examples/addsvc2/thrift/compile.sh @@ -0,0 +1,5 @@ +#!/usr/bin/env sh + +# See also https://thrift.apache.org/tutorial/go + +thrift -r --gen "go:package_prefix=github.com/go-kit/kit/examples/addsvc2/thrift/gen-go/,thrift_import=github.com/apache/thrift/lib/go/thrift" addsvc.thrift diff --git a/examples/addsvc2/thrift/gen-go/addsvc/add_service-remote/add_service-remote.go b/examples/addsvc2/thrift/gen-go/addsvc/add_service-remote/add_service-remote.go new file mode 100755 index 000000000..b8ce67ca2 --- /dev/null +++ b/examples/addsvc2/thrift/gen-go/addsvc/add_service-remote/add_service-remote.go @@ -0,0 +1,157 @@ +// Autogenerated by Thrift Compiler (0.9.3) +// DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING + +package main + +import ( + "flag" + "fmt" + "github.com/apache/thrift/lib/go/thrift" + "github.com/go-kit/kit/examples/addsvc/thrift/gen-go/addsvc" + "math" + "net" + "net/url" + "os" + "strconv" + "strings" +) + +func Usage() { + fmt.Fprintln(os.Stderr, "Usage of ", os.Args[0], " [-h host:port] [-u url] [-f[ramed]] function [arg1 [arg2...]]:") + flag.PrintDefaults() + fmt.Fprintln(os.Stderr, "\nFunctions:") + fmt.Fprintln(os.Stderr, " SumReply Sum(i64 a, i64 b)") + fmt.Fprintln(os.Stderr, " ConcatReply Concat(string a, string b)") + fmt.Fprintln(os.Stderr) + os.Exit(0) +} + +func main() { + flag.Usage = Usage + var host string + var port int + var protocol string + var urlString string + var framed bool + var useHttp bool + var parsedUrl url.URL + var trans thrift.TTransport + _ = strconv.Atoi + _ = math.Abs + flag.Usage = Usage + flag.StringVar(&host, "h", "localhost", "Specify host and port") + flag.IntVar(&port, "p", 9090, "Specify port") + flag.StringVar(&protocol, "P", "binary", "Specify the protocol (binary, compact, simplejson, json)") + flag.StringVar(&urlString, "u", "", "Specify the url") + flag.BoolVar(&framed, "framed", false, "Use framed transport") + flag.BoolVar(&useHttp, "http", false, "Use http") + flag.Parse() + + if len(urlString) > 0 { + parsedUrl, err := url.Parse(urlString) + if err != nil { + fmt.Fprintln(os.Stderr, "Error parsing URL: ", err) + flag.Usage() + } + host = parsedUrl.Host + useHttp = len(parsedUrl.Scheme) <= 0 || parsedUrl.Scheme == "http" + } else if useHttp { + _, err := url.Parse(fmt.Sprint("http://", host, ":", port)) + if err != nil { + fmt.Fprintln(os.Stderr, "Error parsing URL: ", err) + flag.Usage() + } + } + + cmd := flag.Arg(0) + var err error + if useHttp { + trans, err = thrift.NewTHttpClient(parsedUrl.String()) + } else { + portStr := fmt.Sprint(port) + if strings.Contains(host, ":") { + host, portStr, err = net.SplitHostPort(host) + if err != nil { + fmt.Fprintln(os.Stderr, "error with host:", err) + os.Exit(1) + } + } + trans, err = thrift.NewTSocket(net.JoinHostPort(host, portStr)) + if err != nil { + fmt.Fprintln(os.Stderr, "error resolving address:", err) + os.Exit(1) + } + if framed { + trans = thrift.NewTFramedTransport(trans) + } + } + if err != nil { + fmt.Fprintln(os.Stderr, "Error creating transport", err) + os.Exit(1) + } + defer trans.Close() + var protocolFactory thrift.TProtocolFactory + switch protocol { + case "compact": + protocolFactory = thrift.NewTCompactProtocolFactory() + break + case "simplejson": + protocolFactory = thrift.NewTSimpleJSONProtocolFactory() + break + case "json": + protocolFactory = thrift.NewTJSONProtocolFactory() + break + case "binary", "": + protocolFactory = thrift.NewTBinaryProtocolFactoryDefault() + break + default: + fmt.Fprintln(os.Stderr, "Invalid protocol specified: ", protocol) + Usage() + os.Exit(1) + } + client := addsvc.NewAddServiceClientFactory(trans, protocolFactory) + if err := trans.Open(); err != nil { + fmt.Fprintln(os.Stderr, "Error opening socket to ", host, ":", port, " ", err) + os.Exit(1) + } + + switch cmd { + case "Sum": + if flag.NArg()-1 != 2 { + fmt.Fprintln(os.Stderr, "Sum requires 2 args") + flag.Usage() + } + argvalue0, err6 := (strconv.ParseInt(flag.Arg(1), 10, 64)) + if err6 != nil { + Usage() + return + } + value0 := argvalue0 + argvalue1, err7 := (strconv.ParseInt(flag.Arg(2), 10, 64)) + if err7 != nil { + Usage() + return + } + value1 := argvalue1 + fmt.Print(client.Sum(value0, value1)) + fmt.Print("\n") + break + case "Concat": + if flag.NArg()-1 != 2 { + fmt.Fprintln(os.Stderr, "Concat requires 2 args") + flag.Usage() + } + argvalue0 := flag.Arg(1) + value0 := argvalue0 + argvalue1 := flag.Arg(2) + value1 := argvalue1 + fmt.Print(client.Concat(value0, value1)) + fmt.Print("\n") + break + case "": + Usage() + break + default: + fmt.Fprintln(os.Stderr, "Invalid function ", cmd) + } +} diff --git a/examples/addsvc2/thrift/gen-go/addsvc/addservice.go b/examples/addsvc2/thrift/gen-go/addsvc/addservice.go new file mode 100644 index 000000000..3f3aeebf1 --- /dev/null +++ b/examples/addsvc2/thrift/gen-go/addsvc/addservice.go @@ -0,0 +1,807 @@ +// Autogenerated by Thrift Compiler (0.9.3) +// DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING + +package addsvc + +import ( + "bytes" + "fmt" + "github.com/apache/thrift/lib/go/thrift" +) + +// (needed to ensure safety because of naive import list construction.) +var _ = thrift.ZERO +var _ = fmt.Printf +var _ = bytes.Equal + +type AddService interface { + // Parameters: + // - A + // - B + Sum(a int64, b int64) (r *SumReply, err error) + // Parameters: + // - A + // - B + Concat(a string, b string) (r *ConcatReply, err error) +} + +type AddServiceClient struct { + Transport thrift.TTransport + ProtocolFactory thrift.TProtocolFactory + InputProtocol thrift.TProtocol + OutputProtocol thrift.TProtocol + SeqId int32 +} + +func NewAddServiceClientFactory(t thrift.TTransport, f thrift.TProtocolFactory) *AddServiceClient { + return &AddServiceClient{Transport: t, + ProtocolFactory: f, + InputProtocol: f.GetProtocol(t), + OutputProtocol: f.GetProtocol(t), + SeqId: 0, + } +} + +func NewAddServiceClientProtocol(t thrift.TTransport, iprot thrift.TProtocol, oprot thrift.TProtocol) *AddServiceClient { + return &AddServiceClient{Transport: t, + ProtocolFactory: nil, + InputProtocol: iprot, + OutputProtocol: oprot, + SeqId: 0, + } +} + +// Parameters: +// - A +// - B +func (p *AddServiceClient) Sum(a int64, b int64) (r *SumReply, err error) { + if err = p.sendSum(a, b); err != nil { + return + } + return p.recvSum() +} + +func (p *AddServiceClient) sendSum(a int64, b int64) (err error) { + oprot := p.OutputProtocol + if oprot == nil { + oprot = p.ProtocolFactory.GetProtocol(p.Transport) + p.OutputProtocol = oprot + } + p.SeqId++ + if err = oprot.WriteMessageBegin("Sum", thrift.CALL, p.SeqId); err != nil { + return + } + args := AddServiceSumArgs{ + A: a, + B: b, + } + if err = args.Write(oprot); err != nil { + return + } + if err = oprot.WriteMessageEnd(); err != nil { + return + } + return oprot.Flush() +} + +func (p *AddServiceClient) recvSum() (value *SumReply, err error) { + iprot := p.InputProtocol + if iprot == nil { + iprot = p.ProtocolFactory.GetProtocol(p.Transport) + p.InputProtocol = iprot + } + method, mTypeId, seqId, err := iprot.ReadMessageBegin() + if err != nil { + return + } + if method != "Sum" { + err = thrift.NewTApplicationException(thrift.WRONG_METHOD_NAME, "Sum failed: wrong method name") + return + } + if p.SeqId != seqId { + err = thrift.NewTApplicationException(thrift.BAD_SEQUENCE_ID, "Sum failed: out of sequence response") + return + } + if mTypeId == thrift.EXCEPTION { + error0 := thrift.NewTApplicationException(thrift.UNKNOWN_APPLICATION_EXCEPTION, "Unknown Exception") + var error1 error + error1, err = error0.Read(iprot) + if err != nil { + return + } + if err = iprot.ReadMessageEnd(); err != nil { + return + } + err = error1 + return + } + if mTypeId != thrift.REPLY { + err = thrift.NewTApplicationException(thrift.INVALID_MESSAGE_TYPE_EXCEPTION, "Sum failed: invalid message type") + return + } + result := AddServiceSumResult{} + if err = result.Read(iprot); err != nil { + return + } + if err = iprot.ReadMessageEnd(); err != nil { + return + } + value = result.GetSuccess() + return +} + +// Parameters: +// - A +// - B +func (p *AddServiceClient) Concat(a string, b string) (r *ConcatReply, err error) { + if err = p.sendConcat(a, b); err != nil { + return + } + return p.recvConcat() +} + +func (p *AddServiceClient) sendConcat(a string, b string) (err error) { + oprot := p.OutputProtocol + if oprot == nil { + oprot = p.ProtocolFactory.GetProtocol(p.Transport) + p.OutputProtocol = oprot + } + p.SeqId++ + if err = oprot.WriteMessageBegin("Concat", thrift.CALL, p.SeqId); err != nil { + return + } + args := AddServiceConcatArgs{ + A: a, + B: b, + } + if err = args.Write(oprot); err != nil { + return + } + if err = oprot.WriteMessageEnd(); err != nil { + return + } + return oprot.Flush() +} + +func (p *AddServiceClient) recvConcat() (value *ConcatReply, err error) { + iprot := p.InputProtocol + if iprot == nil { + iprot = p.ProtocolFactory.GetProtocol(p.Transport) + p.InputProtocol = iprot + } + method, mTypeId, seqId, err := iprot.ReadMessageBegin() + if err != nil { + return + } + if method != "Concat" { + err = thrift.NewTApplicationException(thrift.WRONG_METHOD_NAME, "Concat failed: wrong method name") + return + } + if p.SeqId != seqId { + err = thrift.NewTApplicationException(thrift.BAD_SEQUENCE_ID, "Concat failed: out of sequence response") + return + } + if mTypeId == thrift.EXCEPTION { + error2 := thrift.NewTApplicationException(thrift.UNKNOWN_APPLICATION_EXCEPTION, "Unknown Exception") + var error3 error + error3, err = error2.Read(iprot) + if err != nil { + return + } + if err = iprot.ReadMessageEnd(); err != nil { + return + } + err = error3 + return + } + if mTypeId != thrift.REPLY { + err = thrift.NewTApplicationException(thrift.INVALID_MESSAGE_TYPE_EXCEPTION, "Concat failed: invalid message type") + return + } + result := AddServiceConcatResult{} + if err = result.Read(iprot); err != nil { + return + } + if err = iprot.ReadMessageEnd(); err != nil { + return + } + value = result.GetSuccess() + return +} + +type AddServiceProcessor struct { + processorMap map[string]thrift.TProcessorFunction + handler AddService +} + +func (p *AddServiceProcessor) AddToProcessorMap(key string, processor thrift.TProcessorFunction) { + p.processorMap[key] = processor +} + +func (p *AddServiceProcessor) GetProcessorFunction(key string) (processor thrift.TProcessorFunction, ok bool) { + processor, ok = p.processorMap[key] + return processor, ok +} + +func (p *AddServiceProcessor) ProcessorMap() map[string]thrift.TProcessorFunction { + return p.processorMap +} + +func NewAddServiceProcessor(handler AddService) *AddServiceProcessor { + + self4 := &AddServiceProcessor{handler: handler, processorMap: make(map[string]thrift.TProcessorFunction)} + self4.processorMap["Sum"] = &addServiceProcessorSum{handler: handler} + self4.processorMap["Concat"] = &addServiceProcessorConcat{handler: handler} + return self4 +} + +func (p *AddServiceProcessor) Process(iprot, oprot thrift.TProtocol) (success bool, err thrift.TException) { + name, _, seqId, err := iprot.ReadMessageBegin() + if err != nil { + return false, err + } + if processor, ok := p.GetProcessorFunction(name); ok { + return processor.Process(seqId, iprot, oprot) + } + iprot.Skip(thrift.STRUCT) + iprot.ReadMessageEnd() + x5 := thrift.NewTApplicationException(thrift.UNKNOWN_METHOD, "Unknown function "+name) + oprot.WriteMessageBegin(name, thrift.EXCEPTION, seqId) + x5.Write(oprot) + oprot.WriteMessageEnd() + oprot.Flush() + return false, x5 + +} + +type addServiceProcessorSum struct { + handler AddService +} + +func (p *addServiceProcessorSum) Process(seqId int32, iprot, oprot thrift.TProtocol) (success bool, err thrift.TException) { + args := AddServiceSumArgs{} + if err = args.Read(iprot); err != nil { + iprot.ReadMessageEnd() + x := thrift.NewTApplicationException(thrift.PROTOCOL_ERROR, err.Error()) + oprot.WriteMessageBegin("Sum", thrift.EXCEPTION, seqId) + x.Write(oprot) + oprot.WriteMessageEnd() + oprot.Flush() + return false, err + } + + iprot.ReadMessageEnd() + result := AddServiceSumResult{} + var retval *SumReply + var err2 error + if retval, err2 = p.handler.Sum(args.A, args.B); err2 != nil { + x := thrift.NewTApplicationException(thrift.INTERNAL_ERROR, "Internal error processing Sum: "+err2.Error()) + oprot.WriteMessageBegin("Sum", thrift.EXCEPTION, seqId) + x.Write(oprot) + oprot.WriteMessageEnd() + oprot.Flush() + return true, err2 + } else { + result.Success = retval + } + if err2 = oprot.WriteMessageBegin("Sum", thrift.REPLY, seqId); err2 != nil { + err = err2 + } + if err2 = result.Write(oprot); err == nil && err2 != nil { + err = err2 + } + if err2 = oprot.WriteMessageEnd(); err == nil && err2 != nil { + err = err2 + } + if err2 = oprot.Flush(); err == nil && err2 != nil { + err = err2 + } + if err != nil { + return + } + return true, err +} + +type addServiceProcessorConcat struct { + handler AddService +} + +func (p *addServiceProcessorConcat) Process(seqId int32, iprot, oprot thrift.TProtocol) (success bool, err thrift.TException) { + args := AddServiceConcatArgs{} + if err = args.Read(iprot); err != nil { + iprot.ReadMessageEnd() + x := thrift.NewTApplicationException(thrift.PROTOCOL_ERROR, err.Error()) + oprot.WriteMessageBegin("Concat", thrift.EXCEPTION, seqId) + x.Write(oprot) + oprot.WriteMessageEnd() + oprot.Flush() + return false, err + } + + iprot.ReadMessageEnd() + result := AddServiceConcatResult{} + var retval *ConcatReply + var err2 error + if retval, err2 = p.handler.Concat(args.A, args.B); err2 != nil { + x := thrift.NewTApplicationException(thrift.INTERNAL_ERROR, "Internal error processing Concat: "+err2.Error()) + oprot.WriteMessageBegin("Concat", thrift.EXCEPTION, seqId) + x.Write(oprot) + oprot.WriteMessageEnd() + oprot.Flush() + return true, err2 + } else { + result.Success = retval + } + if err2 = oprot.WriteMessageBegin("Concat", thrift.REPLY, seqId); err2 != nil { + err = err2 + } + if err2 = result.Write(oprot); err == nil && err2 != nil { + err = err2 + } + if err2 = oprot.WriteMessageEnd(); err == nil && err2 != nil { + err = err2 + } + if err2 = oprot.Flush(); err == nil && err2 != nil { + err = err2 + } + if err != nil { + return + } + return true, err +} + +// HELPER FUNCTIONS AND STRUCTURES + +// Attributes: +// - A +// - B +type AddServiceSumArgs struct { + A int64 `thrift:"a,1" json:"a"` + B int64 `thrift:"b,2" json:"b"` +} + +func NewAddServiceSumArgs() *AddServiceSumArgs { + return &AddServiceSumArgs{} +} + +func (p *AddServiceSumArgs) GetA() int64 { + return p.A +} + +func (p *AddServiceSumArgs) GetB() int64 { + return p.B +} +func (p *AddServiceSumArgs) Read(iprot thrift.TProtocol) error { + if _, err := iprot.ReadStructBegin(); err != nil { + return thrift.PrependError(fmt.Sprintf("%T read error: ", p), err) + } + + for { + _, fieldTypeId, fieldId, err := iprot.ReadFieldBegin() + if err != nil { + return thrift.PrependError(fmt.Sprintf("%T field %d read error: ", p, fieldId), err) + } + if fieldTypeId == thrift.STOP { + break + } + switch fieldId { + case 1: + if err := p.readField1(iprot); err != nil { + return err + } + case 2: + if err := p.readField2(iprot); err != nil { + return err + } + default: + if err := iprot.Skip(fieldTypeId); err != nil { + return err + } + } + if err := iprot.ReadFieldEnd(); err != nil { + return err + } + } + if err := iprot.ReadStructEnd(); err != nil { + return thrift.PrependError(fmt.Sprintf("%T read struct end error: ", p), err) + } + return nil +} + +func (p *AddServiceSumArgs) readField1(iprot thrift.TProtocol) error { + if v, err := iprot.ReadI64(); err != nil { + return thrift.PrependError("error reading field 1: ", err) + } else { + p.A = v + } + return nil +} + +func (p *AddServiceSumArgs) readField2(iprot thrift.TProtocol) error { + if v, err := iprot.ReadI64(); err != nil { + return thrift.PrependError("error reading field 2: ", err) + } else { + p.B = v + } + return nil +} + +func (p *AddServiceSumArgs) Write(oprot thrift.TProtocol) error { + if err := oprot.WriteStructBegin("Sum_args"); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write struct begin error: ", p), err) + } + if err := p.writeField1(oprot); err != nil { + return err + } + if err := p.writeField2(oprot); err != nil { + return err + } + if err := oprot.WriteFieldStop(); err != nil { + return thrift.PrependError("write field stop error: ", err) + } + if err := oprot.WriteStructEnd(); err != nil { + return thrift.PrependError("write struct stop error: ", err) + } + return nil +} + +func (p *AddServiceSumArgs) writeField1(oprot thrift.TProtocol) (err error) { + if err := oprot.WriteFieldBegin("a", thrift.I64, 1); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write field begin error 1:a: ", p), err) + } + if err := oprot.WriteI64(int64(p.A)); err != nil { + return thrift.PrependError(fmt.Sprintf("%T.a (1) field write error: ", p), err) + } + if err := oprot.WriteFieldEnd(); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write field end error 1:a: ", p), err) + } + return err +} + +func (p *AddServiceSumArgs) writeField2(oprot thrift.TProtocol) (err error) { + if err := oprot.WriteFieldBegin("b", thrift.I64, 2); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write field begin error 2:b: ", p), err) + } + if err := oprot.WriteI64(int64(p.B)); err != nil { + return thrift.PrependError(fmt.Sprintf("%T.b (2) field write error: ", p), err) + } + if err := oprot.WriteFieldEnd(); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write field end error 2:b: ", p), err) + } + return err +} + +func (p *AddServiceSumArgs) String() string { + if p == nil { + return "" + } + return fmt.Sprintf("AddServiceSumArgs(%+v)", *p) +} + +// Attributes: +// - Success +type AddServiceSumResult struct { + Success *SumReply `thrift:"success,0" json:"success,omitempty"` +} + +func NewAddServiceSumResult() *AddServiceSumResult { + return &AddServiceSumResult{} +} + +var AddServiceSumResult_Success_DEFAULT *SumReply + +func (p *AddServiceSumResult) GetSuccess() *SumReply { + if !p.IsSetSuccess() { + return AddServiceSumResult_Success_DEFAULT + } + return p.Success +} +func (p *AddServiceSumResult) IsSetSuccess() bool { + return p.Success != nil +} + +func (p *AddServiceSumResult) Read(iprot thrift.TProtocol) error { + if _, err := iprot.ReadStructBegin(); err != nil { + return thrift.PrependError(fmt.Sprintf("%T read error: ", p), err) + } + + for { + _, fieldTypeId, fieldId, err := iprot.ReadFieldBegin() + if err != nil { + return thrift.PrependError(fmt.Sprintf("%T field %d read error: ", p, fieldId), err) + } + if fieldTypeId == thrift.STOP { + break + } + switch fieldId { + case 0: + if err := p.readField0(iprot); err != nil { + return err + } + default: + if err := iprot.Skip(fieldTypeId); err != nil { + return err + } + } + if err := iprot.ReadFieldEnd(); err != nil { + return err + } + } + if err := iprot.ReadStructEnd(); err != nil { + return thrift.PrependError(fmt.Sprintf("%T read struct end error: ", p), err) + } + return nil +} + +func (p *AddServiceSumResult) readField0(iprot thrift.TProtocol) error { + p.Success = &SumReply{} + if err := p.Success.Read(iprot); err != nil { + return thrift.PrependError(fmt.Sprintf("%T error reading struct: ", p.Success), err) + } + return nil +} + +func (p *AddServiceSumResult) Write(oprot thrift.TProtocol) error { + if err := oprot.WriteStructBegin("Sum_result"); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write struct begin error: ", p), err) + } + if err := p.writeField0(oprot); err != nil { + return err + } + if err := oprot.WriteFieldStop(); err != nil { + return thrift.PrependError("write field stop error: ", err) + } + if err := oprot.WriteStructEnd(); err != nil { + return thrift.PrependError("write struct stop error: ", err) + } + return nil +} + +func (p *AddServiceSumResult) writeField0(oprot thrift.TProtocol) (err error) { + if p.IsSetSuccess() { + if err := oprot.WriteFieldBegin("success", thrift.STRUCT, 0); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write field begin error 0:success: ", p), err) + } + if err := p.Success.Write(oprot); err != nil { + return thrift.PrependError(fmt.Sprintf("%T error writing struct: ", p.Success), err) + } + if err := oprot.WriteFieldEnd(); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write field end error 0:success: ", p), err) + } + } + return err +} + +func (p *AddServiceSumResult) String() string { + if p == nil { + return "" + } + return fmt.Sprintf("AddServiceSumResult(%+v)", *p) +} + +// Attributes: +// - A +// - B +type AddServiceConcatArgs struct { + A string `thrift:"a,1" json:"a"` + B string `thrift:"b,2" json:"b"` +} + +func NewAddServiceConcatArgs() *AddServiceConcatArgs { + return &AddServiceConcatArgs{} +} + +func (p *AddServiceConcatArgs) GetA() string { + return p.A +} + +func (p *AddServiceConcatArgs) GetB() string { + return p.B +} +func (p *AddServiceConcatArgs) Read(iprot thrift.TProtocol) error { + if _, err := iprot.ReadStructBegin(); err != nil { + return thrift.PrependError(fmt.Sprintf("%T read error: ", p), err) + } + + for { + _, fieldTypeId, fieldId, err := iprot.ReadFieldBegin() + if err != nil { + return thrift.PrependError(fmt.Sprintf("%T field %d read error: ", p, fieldId), err) + } + if fieldTypeId == thrift.STOP { + break + } + switch fieldId { + case 1: + if err := p.readField1(iprot); err != nil { + return err + } + case 2: + if err := p.readField2(iprot); err != nil { + return err + } + default: + if err := iprot.Skip(fieldTypeId); err != nil { + return err + } + } + if err := iprot.ReadFieldEnd(); err != nil { + return err + } + } + if err := iprot.ReadStructEnd(); err != nil { + return thrift.PrependError(fmt.Sprintf("%T read struct end error: ", p), err) + } + return nil +} + +func (p *AddServiceConcatArgs) readField1(iprot thrift.TProtocol) error { + if v, err := iprot.ReadString(); err != nil { + return thrift.PrependError("error reading field 1: ", err) + } else { + p.A = v + } + return nil +} + +func (p *AddServiceConcatArgs) readField2(iprot thrift.TProtocol) error { + if v, err := iprot.ReadString(); err != nil { + return thrift.PrependError("error reading field 2: ", err) + } else { + p.B = v + } + return nil +} + +func (p *AddServiceConcatArgs) Write(oprot thrift.TProtocol) error { + if err := oprot.WriteStructBegin("Concat_args"); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write struct begin error: ", p), err) + } + if err := p.writeField1(oprot); err != nil { + return err + } + if err := p.writeField2(oprot); err != nil { + return err + } + if err := oprot.WriteFieldStop(); err != nil { + return thrift.PrependError("write field stop error: ", err) + } + if err := oprot.WriteStructEnd(); err != nil { + return thrift.PrependError("write struct stop error: ", err) + } + return nil +} + +func (p *AddServiceConcatArgs) writeField1(oprot thrift.TProtocol) (err error) { + if err := oprot.WriteFieldBegin("a", thrift.STRING, 1); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write field begin error 1:a: ", p), err) + } + if err := oprot.WriteString(string(p.A)); err != nil { + return thrift.PrependError(fmt.Sprintf("%T.a (1) field write error: ", p), err) + } + if err := oprot.WriteFieldEnd(); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write field end error 1:a: ", p), err) + } + return err +} + +func (p *AddServiceConcatArgs) writeField2(oprot thrift.TProtocol) (err error) { + if err := oprot.WriteFieldBegin("b", thrift.STRING, 2); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write field begin error 2:b: ", p), err) + } + if err := oprot.WriteString(string(p.B)); err != nil { + return thrift.PrependError(fmt.Sprintf("%T.b (2) field write error: ", p), err) + } + if err := oprot.WriteFieldEnd(); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write field end error 2:b: ", p), err) + } + return err +} + +func (p *AddServiceConcatArgs) String() string { + if p == nil { + return "" + } + return fmt.Sprintf("AddServiceConcatArgs(%+v)", *p) +} + +// Attributes: +// - Success +type AddServiceConcatResult struct { + Success *ConcatReply `thrift:"success,0" json:"success,omitempty"` +} + +func NewAddServiceConcatResult() *AddServiceConcatResult { + return &AddServiceConcatResult{} +} + +var AddServiceConcatResult_Success_DEFAULT *ConcatReply + +func (p *AddServiceConcatResult) GetSuccess() *ConcatReply { + if !p.IsSetSuccess() { + return AddServiceConcatResult_Success_DEFAULT + } + return p.Success +} +func (p *AddServiceConcatResult) IsSetSuccess() bool { + return p.Success != nil +} + +func (p *AddServiceConcatResult) Read(iprot thrift.TProtocol) error { + if _, err := iprot.ReadStructBegin(); err != nil { + return thrift.PrependError(fmt.Sprintf("%T read error: ", p), err) + } + + for { + _, fieldTypeId, fieldId, err := iprot.ReadFieldBegin() + if err != nil { + return thrift.PrependError(fmt.Sprintf("%T field %d read error: ", p, fieldId), err) + } + if fieldTypeId == thrift.STOP { + break + } + switch fieldId { + case 0: + if err := p.readField0(iprot); err != nil { + return err + } + default: + if err := iprot.Skip(fieldTypeId); err != nil { + return err + } + } + if err := iprot.ReadFieldEnd(); err != nil { + return err + } + } + if err := iprot.ReadStructEnd(); err != nil { + return thrift.PrependError(fmt.Sprintf("%T read struct end error: ", p), err) + } + return nil +} + +func (p *AddServiceConcatResult) readField0(iprot thrift.TProtocol) error { + p.Success = &ConcatReply{} + if err := p.Success.Read(iprot); err != nil { + return thrift.PrependError(fmt.Sprintf("%T error reading struct: ", p.Success), err) + } + return nil +} + +func (p *AddServiceConcatResult) Write(oprot thrift.TProtocol) error { + if err := oprot.WriteStructBegin("Concat_result"); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write struct begin error: ", p), err) + } + if err := p.writeField0(oprot); err != nil { + return err + } + if err := oprot.WriteFieldStop(); err != nil { + return thrift.PrependError("write field stop error: ", err) + } + if err := oprot.WriteStructEnd(); err != nil { + return thrift.PrependError("write struct stop error: ", err) + } + return nil +} + +func (p *AddServiceConcatResult) writeField0(oprot thrift.TProtocol) (err error) { + if p.IsSetSuccess() { + if err := oprot.WriteFieldBegin("success", thrift.STRUCT, 0); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write field begin error 0:success: ", p), err) + } + if err := p.Success.Write(oprot); err != nil { + return thrift.PrependError(fmt.Sprintf("%T error writing struct: ", p.Success), err) + } + if err := oprot.WriteFieldEnd(); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write field end error 0:success: ", p), err) + } + } + return err +} + +func (p *AddServiceConcatResult) String() string { + if p == nil { + return "" + } + return fmt.Sprintf("AddServiceConcatResult(%+v)", *p) +} diff --git a/examples/addsvc2/thrift/gen-go/addsvc/constants.go b/examples/addsvc2/thrift/gen-go/addsvc/constants.go new file mode 100644 index 000000000..2f0079acc --- /dev/null +++ b/examples/addsvc2/thrift/gen-go/addsvc/constants.go @@ -0,0 +1,18 @@ +// Autogenerated by Thrift Compiler (0.9.3) +// DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING + +package addsvc + +import ( + "bytes" + "fmt" + "github.com/apache/thrift/lib/go/thrift" +) + +// (needed to ensure safety because of naive import list construction.) +var _ = thrift.ZERO +var _ = fmt.Printf +var _ = bytes.Equal + +func init() { +} diff --git a/examples/addsvc2/thrift/gen-go/addsvc/ttypes.go b/examples/addsvc2/thrift/gen-go/addsvc/ttypes.go new file mode 100644 index 000000000..2fcbd55ea --- /dev/null +++ b/examples/addsvc2/thrift/gen-go/addsvc/ttypes.go @@ -0,0 +1,269 @@ +// Autogenerated by Thrift Compiler (0.9.3) +// DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING + +package addsvc + +import ( + "bytes" + "fmt" + "github.com/apache/thrift/lib/go/thrift" +) + +// (needed to ensure safety because of naive import list construction.) +var _ = thrift.ZERO +var _ = fmt.Printf +var _ = bytes.Equal + +var GoUnusedProtection__ int + +// Attributes: +// - Value +// - Err +type SumReply struct { + Value int64 `thrift:"value,1" json:"value"` + Err string `thrift:"err,2" json:"err"` +} + +func NewSumReply() *SumReply { + return &SumReply{} +} + +func (p *SumReply) GetValue() int64 { + return p.Value +} + +func (p *SumReply) GetErr() string { + return p.Err +} +func (p *SumReply) Read(iprot thrift.TProtocol) error { + if _, err := iprot.ReadStructBegin(); err != nil { + return thrift.PrependError(fmt.Sprintf("%T read error: ", p), err) + } + + for { + _, fieldTypeId, fieldId, err := iprot.ReadFieldBegin() + if err != nil { + return thrift.PrependError(fmt.Sprintf("%T field %d read error: ", p, fieldId), err) + } + if fieldTypeId == thrift.STOP { + break + } + switch fieldId { + case 1: + if err := p.readField1(iprot); err != nil { + return err + } + case 2: + if err := p.readField2(iprot); err != nil { + return err + } + default: + if err := iprot.Skip(fieldTypeId); err != nil { + return err + } + } + if err := iprot.ReadFieldEnd(); err != nil { + return err + } + } + if err := iprot.ReadStructEnd(); err != nil { + return thrift.PrependError(fmt.Sprintf("%T read struct end error: ", p), err) + } + return nil +} + +func (p *SumReply) readField1(iprot thrift.TProtocol) error { + if v, err := iprot.ReadI64(); err != nil { + return thrift.PrependError("error reading field 1: ", err) + } else { + p.Value = v + } + return nil +} + +func (p *SumReply) readField2(iprot thrift.TProtocol) error { + if v, err := iprot.ReadString(); err != nil { + return thrift.PrependError("error reading field 2: ", err) + } else { + p.Err = v + } + return nil +} + +func (p *SumReply) Write(oprot thrift.TProtocol) error { + if err := oprot.WriteStructBegin("SumReply"); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write struct begin error: ", p), err) + } + if err := p.writeField1(oprot); err != nil { + return err + } + if err := p.writeField2(oprot); err != nil { + return err + } + if err := oprot.WriteFieldStop(); err != nil { + return thrift.PrependError("write field stop error: ", err) + } + if err := oprot.WriteStructEnd(); err != nil { + return thrift.PrependError("write struct stop error: ", err) + } + return nil +} + +func (p *SumReply) writeField1(oprot thrift.TProtocol) (err error) { + if err := oprot.WriteFieldBegin("value", thrift.I64, 1); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write field begin error 1:value: ", p), err) + } + if err := oprot.WriteI64(int64(p.Value)); err != nil { + return thrift.PrependError(fmt.Sprintf("%T.value (1) field write error: ", p), err) + } + if err := oprot.WriteFieldEnd(); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write field end error 1:value: ", p), err) + } + return err +} + +func (p *SumReply) writeField2(oprot thrift.TProtocol) (err error) { + if err := oprot.WriteFieldBegin("err", thrift.STRING, 2); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write field begin error 2:err: ", p), err) + } + if err := oprot.WriteString(string(p.Err)); err != nil { + return thrift.PrependError(fmt.Sprintf("%T.err (2) field write error: ", p), err) + } + if err := oprot.WriteFieldEnd(); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write field end error 2:err: ", p), err) + } + return err +} + +func (p *SumReply) String() string { + if p == nil { + return "" + } + return fmt.Sprintf("SumReply(%+v)", *p) +} + +// Attributes: +// - Value +// - Err +type ConcatReply struct { + Value string `thrift:"value,1" json:"value"` + Err string `thrift:"err,2" json:"err"` +} + +func NewConcatReply() *ConcatReply { + return &ConcatReply{} +} + +func (p *ConcatReply) GetValue() string { + return p.Value +} + +func (p *ConcatReply) GetErr() string { + return p.Err +} +func (p *ConcatReply) Read(iprot thrift.TProtocol) error { + if _, err := iprot.ReadStructBegin(); err != nil { + return thrift.PrependError(fmt.Sprintf("%T read error: ", p), err) + } + + for { + _, fieldTypeId, fieldId, err := iprot.ReadFieldBegin() + if err != nil { + return thrift.PrependError(fmt.Sprintf("%T field %d read error: ", p, fieldId), err) + } + if fieldTypeId == thrift.STOP { + break + } + switch fieldId { + case 1: + if err := p.readField1(iprot); err != nil { + return err + } + case 2: + if err := p.readField2(iprot); err != nil { + return err + } + default: + if err := iprot.Skip(fieldTypeId); err != nil { + return err + } + } + if err := iprot.ReadFieldEnd(); err != nil { + return err + } + } + if err := iprot.ReadStructEnd(); err != nil { + return thrift.PrependError(fmt.Sprintf("%T read struct end error: ", p), err) + } + return nil +} + +func (p *ConcatReply) readField1(iprot thrift.TProtocol) error { + if v, err := iprot.ReadString(); err != nil { + return thrift.PrependError("error reading field 1: ", err) + } else { + p.Value = v + } + return nil +} + +func (p *ConcatReply) readField2(iprot thrift.TProtocol) error { + if v, err := iprot.ReadString(); err != nil { + return thrift.PrependError("error reading field 2: ", err) + } else { + p.Err = v + } + return nil +} + +func (p *ConcatReply) Write(oprot thrift.TProtocol) error { + if err := oprot.WriteStructBegin("ConcatReply"); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write struct begin error: ", p), err) + } + if err := p.writeField1(oprot); err != nil { + return err + } + if err := p.writeField2(oprot); err != nil { + return err + } + if err := oprot.WriteFieldStop(); err != nil { + return thrift.PrependError("write field stop error: ", err) + } + if err := oprot.WriteStructEnd(); err != nil { + return thrift.PrependError("write struct stop error: ", err) + } + return nil +} + +func (p *ConcatReply) writeField1(oprot thrift.TProtocol) (err error) { + if err := oprot.WriteFieldBegin("value", thrift.STRING, 1); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write field begin error 1:value: ", p), err) + } + if err := oprot.WriteString(string(p.Value)); err != nil { + return thrift.PrependError(fmt.Sprintf("%T.value (1) field write error: ", p), err) + } + if err := oprot.WriteFieldEnd(); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write field end error 1:value: ", p), err) + } + return err +} + +func (p *ConcatReply) writeField2(oprot thrift.TProtocol) (err error) { + if err := oprot.WriteFieldBegin("err", thrift.STRING, 2); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write field begin error 2:err: ", p), err) + } + if err := oprot.WriteString(string(p.Err)); err != nil { + return thrift.PrependError(fmt.Sprintf("%T.err (2) field write error: ", p), err) + } + if err := oprot.WriteFieldEnd(); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write field end error 2:err: ", p), err) + } + return err +} + +func (p *ConcatReply) String() string { + if p == nil { + return "" + } + return fmt.Sprintf("ConcatReply(%+v)", *p) +} From c6c2d978fd9ace9ba64f446f0b2defb1fcb475a7 Mon Sep 17 00:00:00 2001 From: Peter Bourgon Date: Sun, 16 Jul 2017 23:56:17 -0700 Subject: [PATCH 2/9] examples/addsvc2: better commentary --- examples/addsvc2/cmd/addsvc/addsvc.go | 84 +++++++++++++++++++----- examples/addsvc2/pkg/transport/grpc.go | 4 +- examples/addsvc2/pkg/transport/thrift.go | 4 +- 3 files changed, 70 insertions(+), 22 deletions(-) diff --git a/examples/addsvc2/cmd/addsvc/addsvc.go b/examples/addsvc2/cmd/addsvc/addsvc.go index 8f8f2d3ba..ace0619e8 100644 --- a/examples/addsvc2/cmd/addsvc/addsvc.go +++ b/examples/addsvc2/cmd/addsvc/addsvc.go @@ -9,6 +9,7 @@ import ( "os" "os/signal" "syscall" + "text/tabwriter" "github.com/apache/thrift/lib/go/thrift" "github.com/oklog/oklog/pkg/group" @@ -29,18 +30,24 @@ import ( ) func main() { + // Define our flags. Your service probably won't need to bind listeners for + // *all* supported transports, or support both Zipkin and LightStep, and so + // on, but we do it here for demonstration purposes. + fs := flag.NewFlagSet("addsvc", flag.ExitOnError) var ( - debugAddr = flag.String("debug.addr", ":8080", "Debug and metrics listen address") - httpAddr = flag.String("http-addr", ":8081", "HTTP listen address") - grpcAddr = flag.String("grpc-addr", ":8082", "gRPC listen address") - thriftAddr = flag.String("thrift-addr", ":8082", "Thrift listen address") - thriftProtocol = flag.String("thrift.protocol", "binary", "binary, compact, json, simplejson") - thriftBufferSize = flag.Int("thrift.buffer.size", 0, "0 for unbuffered") - thriftFramed = flag.Bool("thrift.framed", false, "true to enable framing") - zipkinURL = flag.String("zipkin-url", "", "Zipkin collector URL e.g. http://localhost:9411/api/v1/spans") + debugAddr = fs.String("debug.addr", ":8080", "Debug and metrics listen address") + httpAddr = fs.String("http-addr", ":8081", "HTTP listen address") + grpcAddr = fs.String("grpc-addr", ":8082", "gRPC listen address") + thriftAddr = fs.String("thrift-addr", ":8082", "Thrift listen address") + thriftProtocol = fs.String("thrift-protocol", "binary", "binary, compact, json, simplejson") + thriftBuffer = fs.Int("thrift-buffer", 0, "0 for unbuffered") + thriftFramed = fs.Bool("thrift-framed", false, "true to enable framing") + zipkinURL = fs.String("zipkin-url", "", "Zipkin collector URL e.g. http://localhost:9411/api/v1/spans") ) - flag.Parse() + fs.Usage = usageFor(fs, os.Args[0]+" [flags]") + fs.Parse(os.Args[1:]) + // Create a single logger, which we'll use and give to other components. var logger log.Logger { logger = log.NewLogfmtLogger(os.Stderr) @@ -48,6 +55,8 @@ func main() { logger = log.With(logger, "caller", log.DefaultCaller) } + // Determine which tracer to use. We'll pass the tracer to all the + // components that use it, as a dependency. var tracer stdopentracing.Tracer { if *zipkinURL != "" { @@ -75,7 +84,8 @@ func main() { } } - // Our metrics are dependencies, here we create them. + // Create the (sparse) metrics we'll use in the service. They, too, are + // dependencies that we pass to components that use them. var ints, chars metrics.Counter { // Business-level metrics. @@ -103,16 +113,33 @@ func main() { }, []string{"method", "success"}) } + // Build the layers of the service "onion" from the inside out. First, the + // business logic service; then, the set of endpoints that wrap the service; + // and finally, a series of concrete transport adapters. The adapters, like + // the HTTP handler or the gRPC server, are the bridge between Go kit and + // the interfaces that the transports expect. Note that we're not binding + // them to ports or anything yet; we'll do that next. var ( - service = addservice.New(logger, ints, chars) - endpoints = addendpoint.New(service, logger, duration, tracer) - httpHandler = addtransport.NewHTTPHandler(context.Background(), endpoints, logger, tracer) - grpcServer = addtransport.MakeGRPCServer(endpoints, tracer, logger) - thriftHandler = addtransport.MakeThriftHandler(context.Background(), endpoints) + service = addservice.New(logger, ints, chars) + endpoints = addendpoint.New(service, logger, duration, tracer) + httpHandler = addtransport.NewHTTPHandler(context.Background(), endpoints, logger, tracer) + grpcServer = addtransport.NewGRPCServer(endpoints, tracer, logger) + thriftServer = addtransport.NewThriftServer(context.Background(), endpoints) ) + // Now we're to the part of the func main where we want to start actually + // running things, like servers bound to listeners to receive connections. + // + // The method is the same for each component: add a new actor to the group + // struct, which is a combination of 2 anonymous functions: the first + // function actually runs the component, and the second function should + // interrupt the first function and cause it to return. + var g group.Group { + // The debug listener mounts the http.DefaultServeMux, and serves up + // stuff like the Prometheus metrics route, the Go debug and profiling + // routes, and so on. debugListener, err := net.Listen("tcp", *debugAddr) if err != nil { logger.Log("transport", "debug/HTTP", "during", "Listen", "err", err) @@ -126,6 +153,7 @@ func main() { }) } { + // The HTTP listener mounts the Go kit HTTP handler we created. httpListener, err := net.Listen("tcp", *httpAddr) if err != nil { logger.Log("transport", "HTTP", "during", "Listen", "err", err) @@ -139,6 +167,7 @@ func main() { }) } { + // The gRPC listener mounts the Go kit gRPC server we created. grpcListener, err := net.Listen("tcp", *grpcAddr) if err != nil { logger.Log("transport", "gRPC", "during", "Listen", "err", err) @@ -154,6 +183,9 @@ func main() { }) } { + // The Thrift socket mounts the Go kit Thrift server we created earlier. + // There's a lot of boilerplate involved here, related to configuring + // the protocol and transport; blame Thrift. thriftSocket, err := thrift.NewTServerSocket(*thriftAddr) if err != nil { logger.Log("transport", "Thrift", "during", "Listen", "err", err) @@ -175,8 +207,8 @@ func main() { return fmt.Errorf("invalid Thrift protocol %q", *thriftProtocol) } var transportFactory thrift.TTransportFactory - if *thriftBufferSize > 0 { - transportFactory = thrift.NewTBufferedTransportFactory(*thriftBufferSize) + if *thriftBuffer > 0 { + transportFactory = thrift.NewTBufferedTransportFactory(*thriftBuffer) } else { transportFactory = thrift.NewTTransportFactory() } @@ -184,7 +216,7 @@ func main() { transportFactory = thrift.NewTFramedTransportFactory(transportFactory) } return thrift.NewTSimpleServer4( - addthrift.NewAddServiceProcessor(thriftHandler), + addthrift.NewAddServiceProcessor(thriftServer), thriftSocket, transportFactory, protocolFactory, @@ -194,6 +226,7 @@ func main() { }) } { + // This function just sits and waits for ctrl-C. cancelInterrupt := make(chan struct{}) g.Add(func() error { c := make(chan os.Signal, 1) @@ -210,3 +243,18 @@ func main() { } logger.Log("exit", g.Run()) } + +func usageFor(fs *flag.FlagSet, short string) func() { + return func() { + fmt.Fprintf(os.Stderr, "USAGE\n") + fmt.Fprintf(os.Stderr, " %s\n", short) + fmt.Fprintf(os.Stderr, "\n") + fmt.Fprintf(os.Stderr, "FLAGS\n") + w := tabwriter.NewWriter(os.Stderr, 0, 2, 2, ' ', 0) + fs.VisitAll(func(f *flag.Flag) { + fmt.Fprintf(w, "\t-%s %s\t%s\n", f.Name, f.DefValue, f.Usage) + }) + w.Flush() + fmt.Fprintf(os.Stderr, "\n") + } +} diff --git a/examples/addsvc2/pkg/transport/grpc.go b/examples/addsvc2/pkg/transport/grpc.go index bbbb5925c..59eac9346 100644 --- a/examples/addsvc2/pkg/transport/grpc.go +++ b/examples/addsvc2/pkg/transport/grpc.go @@ -15,8 +15,8 @@ import ( "github.com/go-kit/kit/examples/addsvc2/pkg/endpoint" ) -// MakeGRPCServer makes a set of endpoints available as a gRPC AddServer. -func MakeGRPCServer(endpoints endpoint.Set, tracer stdopentracing.Tracer, logger log.Logger) pb.AddServer { +// NewGRPCServer makes a set of endpoints available as a gRPC AddServer. +func NewGRPCServer(endpoints endpoint.Set, tracer stdopentracing.Tracer, logger log.Logger) pb.AddServer { options := []grpctransport.ServerOption{ grpctransport.ServerErrorLogger(logger), } diff --git a/examples/addsvc2/pkg/transport/thrift.go b/examples/addsvc2/pkg/transport/thrift.go index 02beba550..49d99ff85 100644 --- a/examples/addsvc2/pkg/transport/thrift.go +++ b/examples/addsvc2/pkg/transport/thrift.go @@ -9,8 +9,8 @@ import ( thriftadd "github.com/go-kit/kit/examples/addsvc2/thrift/gen-go/addsvc" ) -// MakeThriftHandler makes a set of endpoints available as a Thrift service. -func MakeThriftHandler(ctx context.Context, endpoints addendpoint.Set) thriftadd.AddService { +// NewThriftServer makes a set of endpoints available as a Thrift service. +func NewThriftServer(ctx context.Context, endpoints addendpoint.Set) thriftadd.AddService { return &thriftServer{ ctx: ctx, endpoints: endpoints, From 2ea9d3e7d002e979c0584c7f88645c7e945469bd Mon Sep 17 00:00:00 2001 From: Peter Bourgon Date: Mon, 17 Jul 2017 15:00:47 -0700 Subject: [PATCH 3/9] examples/addsvc2: Appdash and LightStep tracing --- examples/addsvc2/cmd/addsvc/addsvc.go | 34 ++++++++++++++++++++------- 1 file changed, 26 insertions(+), 8 deletions(-) diff --git a/examples/addsvc2/cmd/addsvc/addsvc.go b/examples/addsvc2/cmd/addsvc/addsvc.go index ace0619e8..0d64e227c 100644 --- a/examples/addsvc2/cmd/addsvc/addsvc.go +++ b/examples/addsvc2/cmd/addsvc/addsvc.go @@ -12,11 +12,14 @@ import ( "text/tabwriter" "github.com/apache/thrift/lib/go/thrift" + lightstep "github.com/lightstep/lightstep-tracer-go" "github.com/oklog/oklog/pkg/group" stdopentracing "github.com/opentracing/opentracing-go" zipkin "github.com/openzipkin/zipkin-go-opentracing" stdprometheus "github.com/prometheus/client_golang/prometheus" "google.golang.org/grpc" + "sourcegraph.com/sourcegraph/appdash" + appdashot "sourcegraph.com/sourcegraph/appdash/opentracing" "github.com/go-kit/kit/log" "github.com/go-kit/kit/metrics" @@ -38,11 +41,13 @@ func main() { debugAddr = fs.String("debug.addr", ":8080", "Debug and metrics listen address") httpAddr = fs.String("http-addr", ":8081", "HTTP listen address") grpcAddr = fs.String("grpc-addr", ":8082", "gRPC listen address") - thriftAddr = fs.String("thrift-addr", ":8082", "Thrift listen address") + thriftAddr = fs.String("thrift-addr", ":8083", "Thrift listen address") thriftProtocol = fs.String("thrift-protocol", "binary", "binary, compact, json, simplejson") thriftBuffer = fs.Int("thrift-buffer", 0, "0 for unbuffered") thriftFramed = fs.Bool("thrift-framed", false, "true to enable framing") - zipkinURL = fs.String("zipkin-url", "", "Zipkin collector URL e.g. http://localhost:9411/api/v1/spans") + zipkinURL = fs.String("zipkin-url", "", "Enable Zipkin tracing via a collector URL e.g. http://localhost:9411/api/v1/spans") + lightstepToken = flag.String("lightstep-token", "", "Enable LightStep tracing via a LightStep access token") + appdashAddr = flag.String("appdash-addr", "", "Enable Appdash tracing via an Appdash server host:port") ) fs.Usage = usageFor(fs, os.Args[0]+" [flags]") fs.Parse(os.Args[1:]) @@ -60,7 +65,7 @@ func main() { var tracer stdopentracing.Tracer { if *zipkinURL != "" { - logger.Log("zipkin", *zipkinURL) + logger.Log("tracer", "Zipkin", "URL", *zipkinURL) collector, err := zipkin.NewHTTPCollector(*zipkinURL) if err != nil { logger.Log("err", err) @@ -72,14 +77,23 @@ func main() { hostPort = "localhost:80" serviceName = "addsvc" ) - tracer, err = zipkin.NewTracer(zipkin.NewRecorder( - collector, debug, hostPort, serviceName, - )) + recorder := zipkin.NewRecorder(collector, debug, hostPort, serviceName) + tracer, err = zipkin.NewTracer(recorder) if err != nil { logger.Log("err", err) os.Exit(1) } + } else if *lightstepToken != "" { + logger.Log("tracer", "LightStep") // probably don't want to print out the token :) + tracer = lightstep.NewTracer(lightstep.Options{ + AccessToken: *lightstepToken, + }) + defer lightstep.FlushLightStepTracer(tracer) + } else if *appdashAddr != "" { + logger.Log("tracer", "Appdash", "addr", *appdashAddr) + tracer = appdashot.NewTracer(appdash.NewRemoteCollector(*appdashAddr)) } else { + logger.Log("tracer", "none") tracer = stdopentracing.GlobalTracer() // no-op } } @@ -133,8 +147,12 @@ func main() { // The method is the same for each component: add a new actor to the group // struct, which is a combination of 2 anonymous functions: the first // function actually runs the component, and the second function should - // interrupt the first function and cause it to return. - + // interrupt the first function and cause it to return. It's in these + // functions that we actually bin the Go kit server/handler structs to the + // concrete transports and start them running. + // + // Putting each component into its own block is mostly for aesthetics: it + // clearly demarcates the scope in which each listener/socket may be used. var g group.Group { // The debug listener mounts the http.DefaultServeMux, and serves up From 6cb68cfbfd858abecbe2cb7baab3fb22e8c06023 Mon Sep 17 00:00:00 2001 From: Peter Bourgon Date: Mon, 17 Jul 2017 19:00:29 -0700 Subject: [PATCH 4/9] examples/addsvc2: add addcli --- examples/addsvc2/cmd/addcli/addcli.go | 198 +++++++++++++++++++++++ examples/addsvc2/cmd/addsvc/addsvc.go | 4 +- examples/addsvc2/pkg/endpoint/set.go | 22 +++ examples/addsvc2/pkg/transport/grpc.go | 103 ++++++++++-- examples/addsvc2/pkg/transport/http.go | 107 ++++++++++-- examples/addsvc2/pkg/transport/thrift.go | 66 +++++++- 6 files changed, 464 insertions(+), 36 deletions(-) create mode 100644 examples/addsvc2/cmd/addcli/addcli.go diff --git a/examples/addsvc2/cmd/addcli/addcli.go b/examples/addsvc2/cmd/addcli/addcli.go new file mode 100644 index 000000000..01ee31f22 --- /dev/null +++ b/examples/addsvc2/cmd/addcli/addcli.go @@ -0,0 +1,198 @@ +package main + +import ( + "context" + "flag" + "fmt" + "os" + "strconv" + "text/tabwriter" + "time" + + "google.golang.org/grpc" + + "github.com/apache/thrift/lib/go/thrift" + lightstep "github.com/lightstep/lightstep-tracer-go" + stdopentracing "github.com/opentracing/opentracing-go" + zipkin "github.com/openzipkin/zipkin-go-opentracing" + "sourcegraph.com/sourcegraph/appdash" + appdashot "sourcegraph.com/sourcegraph/appdash/opentracing" + + "github.com/go-kit/kit/log" + + addservice "github.com/go-kit/kit/examples/addsvc2/pkg/service" + addtransport "github.com/go-kit/kit/examples/addsvc2/pkg/transport" + addthrift "github.com/go-kit/kit/examples/addsvc2/thrift/gen-go/addsvc" +) + +func main() { + // The addcli presumes no service discovery system, and expects users to + // provide the direct address of an addsvc. This presumption is reflected in + // the addcli binary and the the client packages: the -transport.addr flags + // and various client constructors both expect host:port strings. For an + // example service with a client built on top of a service discovery system, + // see profilesvc. + fs := flag.NewFlagSet("addcli", flag.ExitOnError) + var ( + httpAddr = fs.String("http-addr", "", "HTTP address of addsvc") + grpcAddr = fs.String("grpc-addr", "", "gRPC address of addsvc") + thriftAddr = fs.String("thrift-addr", "", "Thrift address of addsvc") + thriftProtocol = fs.String("thrift-protocol", "binary", "binary, compact, json, simplejson") + thriftBuffer = fs.Int("thrift-buffer", 0, "0 for unbuffered") + thriftFramed = fs.Bool("thrift-framed", false, "true to enable framing") + zipkinURL = fs.String("zipkin-url", "", "Enable Zipkin tracing via a collector URL e.g. http://localhost:9411/api/v1/spans") + lightstepToken = flag.String("lightstep-token", "", "Enable LightStep tracing via a LightStep access token") + appdashAddr = flag.String("appdash-addr", "", "Enable Appdash tracing via an Appdash server host:port") + method = fs.String("method", "sum", "sum, concat") + ) + fs.Usage = usageFor(fs, os.Args[0]+" [flags] ") + fs.Parse(os.Args[1:]) + if len(fs.Args()) != 2 { + fs.Usage() + os.Exit(1) + } + + // This is a demonstration client, which supports multiple tracers. + // Your clients will probably just use one tracer. + var tracer stdopentracing.Tracer + { + if *zipkinURL != "" { + collector, err := zipkin.NewHTTPCollector(*zipkinURL) + if err != nil { + fmt.Fprintln(os.Stderr, err.Error()) + os.Exit(1) + } + defer collector.Close() + var ( + debug = false + hostPort = "localhost:80" + serviceName = "addsvc" + ) + recorder := zipkin.NewRecorder(collector, debug, hostPort, serviceName) + tracer, err = zipkin.NewTracer(recorder) + if err != nil { + fmt.Fprintln(os.Stderr, err.Error()) + os.Exit(1) + } + } else if *lightstepToken != "" { + tracer = lightstep.NewTracer(lightstep.Options{ + AccessToken: *lightstepToken, + }) + defer lightstep.FlushLightStepTracer(tracer) + } else if *appdashAddr != "" { + tracer = appdashot.NewTracer(appdash.NewRemoteCollector(*appdashAddr)) + } else { + tracer = stdopentracing.GlobalTracer() // no-op + } + } + + // This is a demonstration client, which supports multiple transports. + // Your clients will probably just define and stick with 1 transport. + var ( + svc addservice.Service + err error + ) + if *httpAddr != "" { + svc, err = addtransport.NewHTTPClient(*httpAddr, tracer, log.NewNopLogger()) + } else if *grpcAddr != "" { + conn, err := grpc.Dial(*grpcAddr, grpc.WithInsecure(), grpc.WithTimeout(time.Second)) + if err != nil { + fmt.Fprintf(os.Stderr, "error: %v", err) + os.Exit(1) + } + defer conn.Close() + svc = addtransport.NewGRPCClient(conn, tracer, log.NewNopLogger()) + } else if *thriftAddr != "" { + // It's necessary to do all of this construction in the func main, + // because (among other reasons) we need to control the lifecycle of the + // Thrift transport, i.e. close it eventually. + var protocolFactory thrift.TProtocolFactory + switch *thriftProtocol { + case "compact": + protocolFactory = thrift.NewTCompactProtocolFactory() + case "simplejson": + protocolFactory = thrift.NewTSimpleJSONProtocolFactory() + case "json": + protocolFactory = thrift.NewTJSONProtocolFactory() + case "binary", "": + protocolFactory = thrift.NewTBinaryProtocolFactoryDefault() + default: + fmt.Fprintf(os.Stderr, "error: invalid protocol %q\n", *thriftProtocol) + os.Exit(1) + } + var transportFactory thrift.TTransportFactory + if *thriftBuffer > 0 { + transportFactory = thrift.NewTBufferedTransportFactory(*thriftBuffer) + } else { + transportFactory = thrift.NewTTransportFactory() + } + if *thriftFramed { + transportFactory = thrift.NewTFramedTransportFactory(transportFactory) + } + transportSocket, err := thrift.NewTSocket(*thriftAddr) + if err != nil { + fmt.Fprintf(os.Stderr, "error: %v\n", err) + os.Exit(1) + } + transport, err := transportFactory.GetTransport(transportSocket) + if err != nil { + fmt.Fprintf(os.Stderr, "error: %v\n", err) + os.Exit(1) + } + if err := transport.Open(); err != nil { + fmt.Fprintf(os.Stderr, "error: %v\n", err) + os.Exit(1) + } + defer transport.Close() + client := addthrift.NewAddServiceClientFactory(transport, protocolFactory) + svc = addtransport.NewThriftClient(client) + } else { + fmt.Fprintf(os.Stderr, "error: no remote address specified\n") + os.Exit(1) + } + if err != nil { + fmt.Fprintf(os.Stderr, "error: %v\n", err) + os.Exit(1) + } + + switch *method { + case "sum": + a, _ := strconv.ParseInt(fs.Args()[0], 10, 64) + b, _ := strconv.ParseInt(fs.Args()[1], 10, 64) + v, err := svc.Sum(context.Background(), int(a), int(b)) + if err != nil { + fmt.Fprintf(os.Stderr, "error: %v\n", err) + os.Exit(1) + } + fmt.Fprintf(os.Stdout, "%d + %d = %d\n", a, b, v) + + case "concat": + a := fs.Args()[0] + b := fs.Args()[1] + v, err := svc.Concat(context.Background(), a, b) + if err != nil { + fmt.Fprintf(os.Stderr, "error: %v\n", err) + os.Exit(1) + } + fmt.Fprintf(os.Stdout, "%q + %q = %q\n", a, b, v) + + default: + fmt.Fprintf(os.Stderr, "error: invalid method %q\n", method) + os.Exit(1) + } +} + +func usageFor(fs *flag.FlagSet, short string) func() { + return func() { + fmt.Fprintf(os.Stderr, "USAGE\n") + fmt.Fprintf(os.Stderr, " %s\n", short) + fmt.Fprintf(os.Stderr, "\n") + fmt.Fprintf(os.Stderr, "FLAGS\n") + w := tabwriter.NewWriter(os.Stderr, 0, 2, 2, ' ', 0) + fs.VisitAll(func(f *flag.Flag) { + fmt.Fprintf(w, "\t-%s %s\t%s\n", f.Name, f.DefValue, f.Usage) + }) + w.Flush() + fmt.Fprintf(os.Stderr, "\n") + } +} diff --git a/examples/addsvc2/cmd/addsvc/addsvc.go b/examples/addsvc2/cmd/addsvc/addsvc.go index 0d64e227c..d7e350061 100644 --- a/examples/addsvc2/cmd/addsvc/addsvc.go +++ b/examples/addsvc2/cmd/addsvc/addsvc.go @@ -17,6 +17,7 @@ import ( stdopentracing "github.com/opentracing/opentracing-go" zipkin "github.com/openzipkin/zipkin-go-opentracing" stdprometheus "github.com/prometheus/client_golang/prometheus" + "github.com/prometheus/client_golang/prometheus/promhttp" "google.golang.org/grpc" "sourcegraph.com/sourcegraph/appdash" appdashot "sourcegraph.com/sourcegraph/appdash/opentracing" @@ -126,6 +127,7 @@ func main() { Help: "Request duration in seconds.", }, []string{"method", "success"}) } + http.DefaultServeMux.Handle("/metrics", promhttp.Handler()) // Build the layers of the service "onion" from the inside out. First, the // business logic service; then, the set of endpoints that wrap the service; @@ -136,7 +138,7 @@ func main() { var ( service = addservice.New(logger, ints, chars) endpoints = addendpoint.New(service, logger, duration, tracer) - httpHandler = addtransport.NewHTTPHandler(context.Background(), endpoints, logger, tracer) + httpHandler = addtransport.NewHTTPHandler(endpoints, tracer, logger) grpcServer = addtransport.NewGRPCServer(endpoints, tracer, logger) thriftServer = addtransport.NewThriftServer(context.Background(), endpoints) ) diff --git a/examples/addsvc2/pkg/endpoint/set.go b/examples/addsvc2/pkg/endpoint/set.go index 6b0630e14..1515aafab 100644 --- a/examples/addsvc2/pkg/endpoint/set.go +++ b/examples/addsvc2/pkg/endpoint/set.go @@ -52,6 +52,28 @@ func New(svc service.Service, logger log.Logger, duration metrics.Histogram, tra } } +// Sum implements the service interface, so Set may be used as a service. +// This is primarily useful in the context of a client library. +func (s Set) Sum(ctx context.Context, a, b int) (int, error) { + resp, err := s.SumEndpoint(ctx, SumRequest{A: a, B: b}) + if err != nil { + return 0, err + } + response := resp.(SumResponse) + return response.V, response.Err +} + +// Concat implements the service interface, so Set may be used as a +// service. This is primarily useful in the context of a client library. +func (s Set) Concat(ctx context.Context, a, b string) (string, error) { + resp, err := s.ConcatEndpoint(ctx, ConcatRequest{A: a, B: b}) + if err != nil { + return "", err + } + response := resp.(ConcatResponse) + return response.V, response.Err +} + // MakeSumEndpoint constructs a Sum endpoint wrapping the service. func MakeSumEndpoint(s service.Service) endpoint.Endpoint { return func(ctx context.Context, request interface{}) (response interface{}, err error) { diff --git a/examples/addsvc2/pkg/transport/grpc.go b/examples/addsvc2/pkg/transport/grpc.go index 59eac9346..24a4864f2 100644 --- a/examples/addsvc2/pkg/transport/grpc.go +++ b/examples/addsvc2/pkg/transport/grpc.go @@ -3,20 +3,34 @@ package transport import ( "context" "errors" + "time" + "google.golang.org/grpc" + + jujuratelimit "github.com/juju/ratelimit" stdopentracing "github.com/opentracing/opentracing-go" + "github.com/sony/gobreaker" oldcontext "golang.org/x/net/context" + "github.com/go-kit/kit/circuitbreaker" + "github.com/go-kit/kit/endpoint" "github.com/go-kit/kit/log" + "github.com/go-kit/kit/ratelimit" "github.com/go-kit/kit/tracing/opentracing" grpctransport "github.com/go-kit/kit/transport/grpc" "github.com/go-kit/kit/examples/addsvc2/pb" - "github.com/go-kit/kit/examples/addsvc2/pkg/endpoint" + addendpoint "github.com/go-kit/kit/examples/addsvc2/pkg/endpoint" + addservice "github.com/go-kit/kit/examples/addsvc2/pkg/service" ) +type grpcServer struct { + sum grpctransport.Handler + concat grpctransport.Handler +} + // NewGRPCServer makes a set of endpoints available as a gRPC AddServer. -func NewGRPCServer(endpoints endpoint.Set, tracer stdopentracing.Tracer, logger log.Logger) pb.AddServer { +func NewGRPCServer(endpoints addendpoint.Set, tracer stdopentracing.Tracer, logger log.Logger) pb.AddServer { options := []grpctransport.ServerOption{ grpctransport.ServerErrorLogger(logger), } @@ -36,11 +50,6 @@ func NewGRPCServer(endpoints endpoint.Set, tracer stdopentracing.Tracer, logger } } -type grpcServer struct { - sum grpctransport.Handler - concat grpctransport.Handler -} - func (s *grpcServer) Sum(ctx oldcontext.Context, req *pb.SumRequest) (*pb.SumReply, error) { _, rep, err := s.sum.ServeGRPC(ctx, req) if err != nil { @@ -57,11 +66,75 @@ func (s *grpcServer) Concat(ctx oldcontext.Context, req *pb.ConcatRequest) (*pb. return rep.(*pb.ConcatReply), nil } +// NewGRPCClient returns an AddService backed by a gRPC server at the other end +// of the conn. The caller is responsible for constructing the conn, and +// eventually closing the underlying transport. +func NewGRPCClient(conn *grpc.ClientConn, tracer stdopentracing.Tracer, logger log.Logger) addservice.Service { + // We construct a single ratelimiter middleware, to limit the total outgoing + // QPS from this client to all methods on the remote instance. We also + // construct per-endpoint circuitbreaker middlewares to demonstrate how + // that's done, although they could easily be combined into a single breaker + // for the entire remote instance, too. + limiter := ratelimit.NewTokenBucketLimiter(jujuratelimit.NewBucketWithRate(100, 100)) + + // Each individual endpoint is an http/transport.Client (which implements + // endpoint.Endpoint) that gets wrapped with various middlewares. If you + // made your own client library, you'd do this work there, so your server + // could rely on a consistent set of client behavior. + var sumEndpoint endpoint.Endpoint + { + sumEndpoint = grpctransport.NewClient( + conn, + "pb.Add", + "Sum", + encodeGRPCSumRequest, + decodeGRPCSumResponse, + pb.SumReply{}, + grpctransport.ClientBefore(opentracing.ToGRPCRequest(tracer, logger)), + ).Endpoint() + sumEndpoint = opentracing.TraceClient(tracer, "Sum")(sumEndpoint) + sumEndpoint = limiter(sumEndpoint) + sumEndpoint = circuitbreaker.Gobreaker(gobreaker.NewCircuitBreaker(gobreaker.Settings{ + Name: "Sum", + Timeout: 30 * time.Second, + }))(sumEndpoint) + } + + // The Concat endpoint is the same thing, with slightly different + // middlewares to demonstrate how to specialize per-endpoint. + var concatEndpoint endpoint.Endpoint + { + concatEndpoint = grpctransport.NewClient( + conn, + "pb.Add", + "Concat", + encodeGRPCConcatRequest, + decodeGRPCConcatResponse, + pb.ConcatReply{}, + grpctransport.ClientBefore(opentracing.ToGRPCRequest(tracer, logger)), + ).Endpoint() + concatEndpoint = opentracing.TraceClient(tracer, "Concat")(concatEndpoint) + concatEndpoint = limiter(concatEndpoint) + concatEndpoint = circuitbreaker.Gobreaker(gobreaker.NewCircuitBreaker(gobreaker.Settings{ + Name: "Concat", + Timeout: 10 * time.Second, + }))(concatEndpoint) + } + + // Returning the endpoint.Set as a service.Service relies on the + // endpoint.Set implementing the Service methods. That's just a simple bit + // of glue code. + return addendpoint.Set{ + SumEndpoint: sumEndpoint, + ConcatEndpoint: concatEndpoint, + } +} + // decodeGRPCSumRequest is a transport/grpc.DecodeRequestFunc that converts a // gRPC sum request to a user-domain sum request. Primarily useful in a server. func decodeGRPCSumRequest(_ context.Context, grpcReq interface{}) (interface{}, error) { req := grpcReq.(*pb.SumRequest) - return endpoint.SumRequest{A: int(req.A), B: int(req.B)}, nil + return addendpoint.SumRequest{A: int(req.A), B: int(req.B)}, nil } // decodeGRPCConcatRequest is a transport/grpc.DecodeRequestFunc that converts a @@ -69,14 +142,14 @@ func decodeGRPCSumRequest(_ context.Context, grpcReq interface{}) (interface{}, // server. func decodeGRPCConcatRequest(_ context.Context, grpcReq interface{}) (interface{}, error) { req := grpcReq.(*pb.ConcatRequest) - return endpoint.ConcatRequest{A: req.A, B: req.B}, nil + return addendpoint.ConcatRequest{A: req.A, B: req.B}, nil } // decodeGRPCSumResponse is a transport/grpc.DecodeResponseFunc that converts a // gRPC sum reply to a user-domain sum response. Primarily useful in a client. func decodeGRPCSumResponse(_ context.Context, grpcReply interface{}) (interface{}, error) { reply := grpcReply.(*pb.SumReply) - return endpoint.SumResponse{V: int(reply.V), Err: str2err(reply.Err)}, nil + return addendpoint.SumResponse{V: int(reply.V), Err: str2err(reply.Err)}, nil } // decodeGRPCConcatResponse is a transport/grpc.DecodeResponseFunc that converts @@ -84,13 +157,13 @@ func decodeGRPCSumResponse(_ context.Context, grpcReply interface{}) (interface{ // client. func decodeGRPCConcatResponse(_ context.Context, grpcReply interface{}) (interface{}, error) { reply := grpcReply.(*pb.ConcatReply) - return endpoint.ConcatResponse{V: reply.V, Err: str2err(reply.Err)}, nil + return addendpoint.ConcatResponse{V: reply.V, Err: str2err(reply.Err)}, nil } // encodeGRPCSumResponse is a transport/grpc.EncodeResponseFunc that converts a // user-domain sum response to a gRPC sum reply. Primarily useful in a server. func encodeGRPCSumResponse(_ context.Context, response interface{}) (interface{}, error) { - resp := response.(endpoint.SumResponse) + resp := response.(addendpoint.SumResponse) return &pb.SumReply{V: int64(resp.V), Err: err2str(resp.Err)}, nil } @@ -98,14 +171,14 @@ func encodeGRPCSumResponse(_ context.Context, response interface{}) (interface{} // a user-domain concat response to a gRPC concat reply. Primarily useful in a // server. func encodeGRPCConcatResponse(_ context.Context, response interface{}) (interface{}, error) { - resp := response.(endpoint.ConcatResponse) + resp := response.(addendpoint.ConcatResponse) return &pb.ConcatReply{V: resp.V, Err: err2str(resp.Err)}, nil } // encodeGRPCSumRequest is a transport/grpc.EncodeRequestFunc that converts a // user-domain sum request to a gRPC sum request. Primarily useful in a client. func encodeGRPCSumRequest(_ context.Context, request interface{}) (interface{}, error) { - req := request.(endpoint.SumRequest) + req := request.(addendpoint.SumRequest) return &pb.SumRequest{A: int64(req.A), B: int64(req.B)}, nil } @@ -113,7 +186,7 @@ func encodeGRPCSumRequest(_ context.Context, request interface{}) (interface{}, // user-domain concat request to a gRPC concat request. Primarily useful in a // client. func encodeGRPCConcatRequest(_ context.Context, request interface{}) (interface{}, error) { - req := request.(endpoint.ConcatRequest) + req := request.(addendpoint.ConcatRequest) return &pb.ConcatRequest{A: req.A, B: req.B}, nil } diff --git a/examples/addsvc2/pkg/transport/http.go b/examples/addsvc2/pkg/transport/http.go index 4146b31b3..e011fc315 100644 --- a/examples/addsvc2/pkg/transport/http.go +++ b/examples/addsvc2/pkg/transport/http.go @@ -7,21 +7,28 @@ import ( "errors" "io/ioutil" "net/http" + "net/url" + "strings" + "time" + jujuratelimit "github.com/juju/ratelimit" stdopentracing "github.com/opentracing/opentracing-go" - "github.com/prometheus/client_golang/prometheus/promhttp" + "github.com/sony/gobreaker" + "github.com/go-kit/kit/circuitbreaker" + "github.com/go-kit/kit/endpoint" "github.com/go-kit/kit/log" + "github.com/go-kit/kit/ratelimit" "github.com/go-kit/kit/tracing/opentracing" httptransport "github.com/go-kit/kit/transport/http" - "github.com/go-kit/kit/examples/addsvc2/pkg/endpoint" - "github.com/go-kit/kit/examples/addsvc2/pkg/service" + addendpoint "github.com/go-kit/kit/examples/addsvc2/pkg/endpoint" + addservice "github.com/go-kit/kit/examples/addsvc2/pkg/service" ) // NewHTTPHandler returns an HTTP handler that makes a set of endpoints // available on predefined paths. -func NewHTTPHandler(ctx context.Context, endpoints endpoint.Set, logger log.Logger, trace stdopentracing.Tracer) http.Handler { +func NewHTTPHandler(endpoints addendpoint.Set, tracer stdopentracing.Tracer, logger log.Logger) http.Handler { options := []httptransport.ServerOption{ httptransport.ServerErrorEncoder(errorEncoder), httptransport.ServerErrorLogger(logger), @@ -31,18 +38,92 @@ func NewHTTPHandler(ctx context.Context, endpoints endpoint.Set, logger log.Logg endpoints.SumEndpoint, decodeHTTPSumRequest, encodeHTTPGenericResponse, - append(options, httptransport.ServerBefore(opentracing.FromHTTPRequest(trace, "Sum", logger)))..., + append(options, httptransport.ServerBefore(opentracing.FromHTTPRequest(tracer, "Sum", logger)))..., )) m.Handle("/concat", httptransport.NewServer( endpoints.ConcatEndpoint, decodeHTTPConcatRequest, encodeHTTPGenericResponse, - append(options, httptransport.ServerBefore(opentracing.FromHTTPRequest(trace, "Concat", logger)))..., + append(options, httptransport.ServerBefore(opentracing.FromHTTPRequest(tracer, "Concat", logger)))..., )) - m.Handle("/metrics", promhttp.Handler()) return m } +// NewHTTPClient returns an AddService backed by an HTTP server living at the +// remote instance. We expect instance to come from a service discovery system, +// so likely of the form "host:port". +func NewHTTPClient(instance string, tracer stdopentracing.Tracer, logger log.Logger) (addservice.Service, error) { + // Quickly sanitize the instance string. + if !strings.HasPrefix(instance, "http") { + instance = "http://" + instance + } + u, err := url.Parse(instance) + if err != nil { + return nil, err + } + + // We construct a single ratelimiter middleware, to limit the total outgoing + // QPS from this client to all methods on the remote instance. We also + // construct per-endpoint circuitbreaker middlewares to demonstrate how + // that's done, although they could easily be combined into a single breaker + // for the entire remote instance, too. + limiter := ratelimit.NewTokenBucketLimiter(jujuratelimit.NewBucketWithRate(100, 100)) + + // Each individual endpoint is an http/transport.Client (which implements + // endpoint.Endpoint) that gets wrapped with various middlewares. If you + // made your own client library, you'd do this work there, so your server + // could rely on a consistent set of client behavior. + var sumEndpoint endpoint.Endpoint + { + sumEndpoint = httptransport.NewClient( + "POST", + copyURL(u, "/sum"), + encodeHTTPGenericRequest, + decodeHTTPSumResponse, + httptransport.ClientBefore(opentracing.ToHTTPRequest(tracer, logger)), + ).Endpoint() + sumEndpoint = opentracing.TraceClient(tracer, "Sum")(sumEndpoint) + sumEndpoint = limiter(sumEndpoint) + sumEndpoint = circuitbreaker.Gobreaker(gobreaker.NewCircuitBreaker(gobreaker.Settings{ + Name: "Sum", + Timeout: 30 * time.Second, + }))(sumEndpoint) + } + + // The Concat endpoint is the same thing, with slightly different + // middlewares to demonstrate how to specialize per-endpoint. + var concatEndpoint endpoint.Endpoint + { + concatEndpoint = httptransport.NewClient( + "POST", + copyURL(u, "/concat"), + encodeHTTPGenericRequest, + decodeHTTPConcatResponse, + httptransport.ClientBefore(opentracing.ToHTTPRequest(tracer, logger)), + ).Endpoint() + concatEndpoint = opentracing.TraceClient(tracer, "Concat")(concatEndpoint) + concatEndpoint = limiter(concatEndpoint) + concatEndpoint = circuitbreaker.Gobreaker(gobreaker.NewCircuitBreaker(gobreaker.Settings{ + Name: "Concat", + Timeout: 10 * time.Second, + }))(concatEndpoint) + } + + // Returning the endpoint.Set as a service.Service relies on the + // endpoint.Set implementing the Service methods. That's just a simple bit + // of glue code. + return addendpoint.Set{ + SumEndpoint: sumEndpoint, + ConcatEndpoint: concatEndpoint, + }, nil +} + +func copyURL(base *url.URL, path string) *url.URL { + next := *base + next.Path = path + return &next +} + func errorEncoder(_ context.Context, err error, w http.ResponseWriter) { w.WriteHeader(err2code(err)) json.NewEncoder(w).Encode(errorWrapper{Error: err.Error()}) @@ -50,7 +131,7 @@ func errorEncoder(_ context.Context, err error, w http.ResponseWriter) { func err2code(err error) int { switch err { - case service.ErrTwoZeroes, service.ErrMaxSizeExceeded, service.ErrIntOverflow: + case addservice.ErrTwoZeroes, addservice.ErrMaxSizeExceeded, addservice.ErrIntOverflow: return http.StatusBadRequest } return http.StatusInternalServerError @@ -72,7 +153,7 @@ type errorWrapper struct { // JSON-encoded sum request from the HTTP request body. Primarily useful in a // server. func decodeHTTPSumRequest(_ context.Context, r *http.Request) (interface{}, error) { - var req endpoint.SumRequest + var req addendpoint.SumRequest err := json.NewDecoder(r.Body).Decode(&req) return req, err } @@ -81,7 +162,7 @@ func decodeHTTPSumRequest(_ context.Context, r *http.Request) (interface{}, erro // JSON-encoded concat request from the HTTP request body. Primarily useful in a // server. func decodeHTTPConcatRequest(_ context.Context, r *http.Request) (interface{}, error) { - var req endpoint.ConcatRequest + var req addendpoint.ConcatRequest err := json.NewDecoder(r.Body).Decode(&req) return req, err } @@ -95,7 +176,7 @@ func decodeHTTPSumResponse(_ context.Context, r *http.Response) (interface{}, er if r.StatusCode != http.StatusOK { return nil, errors.New(r.Status) } - var resp endpoint.SumResponse + var resp addendpoint.SumResponse err := json.NewDecoder(r.Body).Decode(&resp) return resp, err } @@ -109,7 +190,7 @@ func decodeHTTPConcatResponse(_ context.Context, r *http.Response) (interface{}, if r.StatusCode != http.StatusOK { return nil, errors.New(r.Status) } - var resp endpoint.ConcatResponse + var resp addendpoint.ConcatResponse err := json.NewDecoder(r.Body).Decode(&resp) return resp, err } @@ -128,7 +209,7 @@ func encodeHTTPGenericRequest(_ context.Context, r *http.Request, request interf // encodeHTTPGenericResponse is a transport/http.EncodeResponseFunc that encodes // the response as JSON to the response writer. Primarily useful in a server. func encodeHTTPGenericResponse(ctx context.Context, w http.ResponseWriter, response interface{}) error { - if f, ok := response.(endpoint.Failer); ok && f.Failed() != nil { + if f, ok := response.(addendpoint.Failer); ok && f.Failed() != nil { errorEncoder(ctx, f.Failed(), w) return nil } diff --git a/examples/addsvc2/pkg/transport/thrift.go b/examples/addsvc2/pkg/transport/thrift.go index 49d99ff85..4ec99c649 100644 --- a/examples/addsvc2/pkg/transport/thrift.go +++ b/examples/addsvc2/pkg/transport/thrift.go @@ -2,13 +2,25 @@ package transport import ( "context" + "time" + jujuratelimit "github.com/juju/ratelimit" + "github.com/sony/gobreaker" + + "github.com/go-kit/kit/circuitbreaker" "github.com/go-kit/kit/endpoint" + "github.com/go-kit/kit/ratelimit" + addendpoint "github.com/go-kit/kit/examples/addsvc2/pkg/endpoint" - "github.com/go-kit/kit/examples/addsvc2/pkg/service" + addservice "github.com/go-kit/kit/examples/addsvc2/pkg/service" thriftadd "github.com/go-kit/kit/examples/addsvc2/thrift/gen-go/addsvc" ) +type thriftServer struct { + ctx context.Context + endpoints addendpoint.Set +} + // NewThriftServer makes a set of endpoints available as a Thrift service. func NewThriftServer(ctx context.Context, endpoints addendpoint.Set) thriftadd.AddService { return &thriftServer{ @@ -17,11 +29,6 @@ func NewThriftServer(ctx context.Context, endpoints addendpoint.Set) thriftadd.A } } -type thriftServer struct { - ctx context.Context - endpoints addendpoint.Set -} - func (s *thriftServer) Sum(a int64, b int64) (*thriftadd.SumReply, error) { request := addendpoint.SumRequest{A: int(a), B: int(b)} response, err := s.endpoints.SumEndpoint(s.ctx, request) @@ -42,13 +49,58 @@ func (s *thriftServer) Concat(a string, b string) (*thriftadd.ConcatReply, error return &thriftadd.ConcatReply{Value: resp.V, Err: err2str(resp.Err)}, nil } +// NewThriftClient returns an AddService backed by a Thrift server described by +// the provided client. The caller is responsible for constructing the client, +// and eventually closing the underlying transport. +func NewThriftClient(client *thriftadd.AddServiceClient) addservice.Service { + // We construct a single ratelimiter middleware, to limit the total outgoing + // QPS from this client to all methods on the remote instance. We also + // construct per-endpoint circuitbreaker middlewares to demonstrate how + // that's done, although they could easily be combined into a single breaker + // for the entire remote instance, too. + limiter := ratelimit.NewTokenBucketLimiter(jujuratelimit.NewBucketWithRate(100, 100)) + + // Each individual endpoint is an http/transport.Client (which implements + // endpoint.Endpoint) that gets wrapped with various middlewares. If you + // could rely on a consistent set of client behavior. + var sumEndpoint endpoint.Endpoint + { + sumEndpoint = MakeThriftSumEndpoint(client) + sumEndpoint = limiter(sumEndpoint) + sumEndpoint = circuitbreaker.Gobreaker(gobreaker.NewCircuitBreaker(gobreaker.Settings{ + Name: "Sum", + Timeout: 30 * time.Second, + }))(sumEndpoint) + } + + // The Concat endpoint is the same thing, with slightly different + // middlewares to demonstrate how to specialize per-endpoint. + var concatEndpoint endpoint.Endpoint + { + concatEndpoint = MakeThriftConcatEndpoint(client) + concatEndpoint = limiter(concatEndpoint) + concatEndpoint = circuitbreaker.Gobreaker(gobreaker.NewCircuitBreaker(gobreaker.Settings{ + Name: "Concat", + Timeout: 10 * time.Second, + }))(concatEndpoint) + } + + // Returning the endpoint.Set as a service.Service relies on the + // endpoint.Set implementing the Service methods. That's just a simple bit + // of glue code. + return addendpoint.Set{ + SumEndpoint: sumEndpoint, + ConcatEndpoint: concatEndpoint, + } +} + // MakeThriftSumEndpoint returns an endpoint that invokes the passed Thrift client. // Useful only in clients, and only until a proper transport/thrift.Client exists. func MakeThriftSumEndpoint(client *thriftadd.AddServiceClient) endpoint.Endpoint { return func(ctx context.Context, request interface{}) (interface{}, error) { req := request.(addendpoint.SumRequest) reply, err := client.Sum(int64(req.A), int64(req.B)) - if err == service.ErrIntOverflow { + if err == addservice.ErrIntOverflow { return nil, err // special case; see comment on ErrIntOverflow } return addendpoint.SumResponse{V: int(reply.Value), Err: err}, nil From 22e82b4a44614d5a49881eba3d415c3d98ce33fa Mon Sep 17 00:00:00 2001 From: Peter Bourgon Date: Mon, 17 Jul 2017 19:04:31 -0700 Subject: [PATCH 5/9] examples/addsvc2: rename pkg/xxx to pkg/addxxx --- examples/addsvc2/cmd/addcli/addcli.go | 4 ++-- examples/addsvc2/cmd/addsvc/addsvc.go | 6 +++--- examples/addsvc2/cmd/addsvc/wiring_test.go | 12 ++++++------ .../pkg/{endpoint => addendpoint}/middleware.go | 2 +- .../addsvc2/pkg/{endpoint => addendpoint}/set.go | 10 +++++----- .../pkg/{service => addservice}/middleware.go | 2 +- .../addsvc2/pkg/{service => addservice}/service.go | 2 +- .../addsvc2/pkg/{transport => addtransport}/grpc.go | 6 +++--- .../addsvc2/pkg/{transport => addtransport}/http.go | 6 +++--- .../pkg/{transport => addtransport}/thrift.go | 6 +++--- 10 files changed, 28 insertions(+), 28 deletions(-) rename examples/addsvc2/pkg/{endpoint => addendpoint}/middleware.go (98%) rename examples/addsvc2/pkg/{endpoint => addendpoint}/set.go (92%) rename examples/addsvc2/pkg/{service => addservice}/middleware.go (98%) rename examples/addsvc2/pkg/{service => addservice}/service.go (98%) rename examples/addsvc2/pkg/{transport => addtransport}/grpc.go (98%) rename examples/addsvc2/pkg/{transport => addtransport}/http.go (98%) rename examples/addsvc2/pkg/{transport => addtransport}/thrift.go (96%) diff --git a/examples/addsvc2/cmd/addcli/addcli.go b/examples/addsvc2/cmd/addcli/addcli.go index 01ee31f22..7af3ce0e7 100644 --- a/examples/addsvc2/cmd/addcli/addcli.go +++ b/examples/addsvc2/cmd/addcli/addcli.go @@ -20,8 +20,8 @@ import ( "github.com/go-kit/kit/log" - addservice "github.com/go-kit/kit/examples/addsvc2/pkg/service" - addtransport "github.com/go-kit/kit/examples/addsvc2/pkg/transport" + "github.com/go-kit/kit/examples/addsvc2/pkg/addservice" + "github.com/go-kit/kit/examples/addsvc2/pkg/addtransport" addthrift "github.com/go-kit/kit/examples/addsvc2/thrift/gen-go/addsvc" ) diff --git a/examples/addsvc2/cmd/addsvc/addsvc.go b/examples/addsvc2/cmd/addsvc/addsvc.go index d7e350061..f5dc077cd 100644 --- a/examples/addsvc2/cmd/addsvc/addsvc.go +++ b/examples/addsvc2/cmd/addsvc/addsvc.go @@ -27,9 +27,9 @@ import ( "github.com/go-kit/kit/metrics/prometheus" addpb "github.com/go-kit/kit/examples/addsvc2/pb" - addendpoint "github.com/go-kit/kit/examples/addsvc2/pkg/endpoint" - addservice "github.com/go-kit/kit/examples/addsvc2/pkg/service" - addtransport "github.com/go-kit/kit/examples/addsvc2/pkg/transport" + "github.com/go-kit/kit/examples/addsvc2/pkg/addendpoint" + "github.com/go-kit/kit/examples/addsvc2/pkg/addservice" + "github.com/go-kit/kit/examples/addsvc2/pkg/addtransport" addthrift "github.com/go-kit/kit/examples/addsvc2/thrift/gen-go/addsvc" ) diff --git a/examples/addsvc2/cmd/addsvc/wiring_test.go b/examples/addsvc2/cmd/addsvc/wiring_test.go index e2133f4cb..fb3dbe0d0 100644 --- a/examples/addsvc2/cmd/addsvc/wiring_test.go +++ b/examples/addsvc2/cmd/addsvc/wiring_test.go @@ -1,26 +1,26 @@ package main import ( - "context" "io/ioutil" "net/http" "net/http/httptest" "strings" "testing" + "github.com/opentracing/opentracing-go" + "github.com/go-kit/kit/log" "github.com/go-kit/kit/metrics/discard" - "github.com/opentracing/opentracing-go" - addendpoint "github.com/go-kit/kit/examples/addsvc2/pkg/endpoint" - addservice "github.com/go-kit/kit/examples/addsvc2/pkg/service" - addtransport "github.com/go-kit/kit/examples/addsvc2/pkg/transport" + "github.com/go-kit/kit/examples/addsvc2/pkg/addendpoint" + "github.com/go-kit/kit/examples/addsvc2/pkg/addservice" + "github.com/go-kit/kit/examples/addsvc2/pkg/addtransport" ) func TestHTTP(t *testing.T) { svc := addservice.New(log.NewNopLogger(), discard.NewCounter(), discard.NewCounter()) eps := addendpoint.New(svc, log.NewNopLogger(), discard.NewHistogram(), opentracing.GlobalTracer()) - mux := addtransport.NewHTTPHandler(context.Background(), eps, log.NewNopLogger(), opentracing.GlobalTracer()) + mux := addtransport.NewHTTPHandler(eps, opentracing.GlobalTracer(), log.NewNopLogger()) srv := httptest.NewServer(mux) defer srv.Close() diff --git a/examples/addsvc2/pkg/endpoint/middleware.go b/examples/addsvc2/pkg/addendpoint/middleware.go similarity index 98% rename from examples/addsvc2/pkg/endpoint/middleware.go rename to examples/addsvc2/pkg/addendpoint/middleware.go index d02bfbefb..c83047b76 100644 --- a/examples/addsvc2/pkg/endpoint/middleware.go +++ b/examples/addsvc2/pkg/addendpoint/middleware.go @@ -1,4 +1,4 @@ -package endpoint +package addendpoint import ( "context" diff --git a/examples/addsvc2/pkg/endpoint/set.go b/examples/addsvc2/pkg/addendpoint/set.go similarity index 92% rename from examples/addsvc2/pkg/endpoint/set.go rename to examples/addsvc2/pkg/addendpoint/set.go index 1515aafab..c8c1c6f42 100644 --- a/examples/addsvc2/pkg/endpoint/set.go +++ b/examples/addsvc2/pkg/addendpoint/set.go @@ -1,4 +1,4 @@ -package endpoint +package addendpoint import ( "context" @@ -14,7 +14,7 @@ import ( "github.com/go-kit/kit/ratelimit" "github.com/go-kit/kit/tracing/opentracing" - "github.com/go-kit/kit/examples/addsvc2/pkg/service" + "github.com/go-kit/kit/examples/addsvc2/pkg/addservice" ) // Set collects all of the endpoints that compose an add service. It's meant to @@ -27,7 +27,7 @@ type Set struct { // New returns a Set that wraps the provided server, and wires in all of the // expected endpoint middlewares via the various parameters. -func New(svc service.Service, logger log.Logger, duration metrics.Histogram, trace stdopentracing.Tracer) Set { +func New(svc addservice.Service, logger log.Logger, duration metrics.Histogram, trace stdopentracing.Tracer) Set { var sumEndpoint endpoint.Endpoint { sumEndpoint = MakeSumEndpoint(svc) @@ -75,7 +75,7 @@ func (s Set) Concat(ctx context.Context, a, b string) (string, error) { } // MakeSumEndpoint constructs a Sum endpoint wrapping the service. -func MakeSumEndpoint(s service.Service) endpoint.Endpoint { +func MakeSumEndpoint(s addservice.Service) endpoint.Endpoint { return func(ctx context.Context, request interface{}) (response interface{}, err error) { req := request.(SumRequest) v, err := s.Sum(ctx, req.A, req.B) @@ -84,7 +84,7 @@ func MakeSumEndpoint(s service.Service) endpoint.Endpoint { } // MakeConcatEndpoint constructs a Concat endpoint wrapping the service. -func MakeConcatEndpoint(s service.Service) endpoint.Endpoint { +func MakeConcatEndpoint(s addservice.Service) endpoint.Endpoint { return func(ctx context.Context, request interface{}) (response interface{}, err error) { req := request.(ConcatRequest) v, err := s.Concat(ctx, req.A, req.B) diff --git a/examples/addsvc2/pkg/service/middleware.go b/examples/addsvc2/pkg/addservice/middleware.go similarity index 98% rename from examples/addsvc2/pkg/service/middleware.go rename to examples/addsvc2/pkg/addservice/middleware.go index ba028e776..5a1d6ee5b 100644 --- a/examples/addsvc2/pkg/service/middleware.go +++ b/examples/addsvc2/pkg/addservice/middleware.go @@ -1,4 +1,4 @@ -package service +package addservice import ( "context" diff --git a/examples/addsvc2/pkg/service/service.go b/examples/addsvc2/pkg/addservice/service.go similarity index 98% rename from examples/addsvc2/pkg/service/service.go rename to examples/addsvc2/pkg/addservice/service.go index 7612cf2ae..d884373bf 100644 --- a/examples/addsvc2/pkg/service/service.go +++ b/examples/addsvc2/pkg/addservice/service.go @@ -1,4 +1,4 @@ -package service +package addservice import ( "context" diff --git a/examples/addsvc2/pkg/transport/grpc.go b/examples/addsvc2/pkg/addtransport/grpc.go similarity index 98% rename from examples/addsvc2/pkg/transport/grpc.go rename to examples/addsvc2/pkg/addtransport/grpc.go index 24a4864f2..f8e4c2bba 100644 --- a/examples/addsvc2/pkg/transport/grpc.go +++ b/examples/addsvc2/pkg/addtransport/grpc.go @@ -1,4 +1,4 @@ -package transport +package addtransport import ( "context" @@ -20,8 +20,8 @@ import ( grpctransport "github.com/go-kit/kit/transport/grpc" "github.com/go-kit/kit/examples/addsvc2/pb" - addendpoint "github.com/go-kit/kit/examples/addsvc2/pkg/endpoint" - addservice "github.com/go-kit/kit/examples/addsvc2/pkg/service" + "github.com/go-kit/kit/examples/addsvc2/pkg/addendpoint" + "github.com/go-kit/kit/examples/addsvc2/pkg/addservice" ) type grpcServer struct { diff --git a/examples/addsvc2/pkg/transport/http.go b/examples/addsvc2/pkg/addtransport/http.go similarity index 98% rename from examples/addsvc2/pkg/transport/http.go rename to examples/addsvc2/pkg/addtransport/http.go index e011fc315..5ab8e679a 100644 --- a/examples/addsvc2/pkg/transport/http.go +++ b/examples/addsvc2/pkg/addtransport/http.go @@ -1,4 +1,4 @@ -package transport +package addtransport import ( "bytes" @@ -22,8 +22,8 @@ import ( "github.com/go-kit/kit/tracing/opentracing" httptransport "github.com/go-kit/kit/transport/http" - addendpoint "github.com/go-kit/kit/examples/addsvc2/pkg/endpoint" - addservice "github.com/go-kit/kit/examples/addsvc2/pkg/service" + "github.com/go-kit/kit/examples/addsvc2/pkg/addendpoint" + "github.com/go-kit/kit/examples/addsvc2/pkg/addservice" ) // NewHTTPHandler returns an HTTP handler that makes a set of endpoints diff --git a/examples/addsvc2/pkg/transport/thrift.go b/examples/addsvc2/pkg/addtransport/thrift.go similarity index 96% rename from examples/addsvc2/pkg/transport/thrift.go rename to examples/addsvc2/pkg/addtransport/thrift.go index 4ec99c649..ebbfc3687 100644 --- a/examples/addsvc2/pkg/transport/thrift.go +++ b/examples/addsvc2/pkg/addtransport/thrift.go @@ -1,4 +1,4 @@ -package transport +package addtransport import ( "context" @@ -11,8 +11,8 @@ import ( "github.com/go-kit/kit/endpoint" "github.com/go-kit/kit/ratelimit" - addendpoint "github.com/go-kit/kit/examples/addsvc2/pkg/endpoint" - addservice "github.com/go-kit/kit/examples/addsvc2/pkg/service" + "github.com/go-kit/kit/examples/addsvc2/pkg/addendpoint" + "github.com/go-kit/kit/examples/addsvc2/pkg/addservice" thriftadd "github.com/go-kit/kit/examples/addsvc2/thrift/gen-go/addsvc" ) From a4706b5472883325a4c305cce438ebb0c969e6e1 Mon Sep 17 00:00:00 2001 From: Peter Bourgon Date: Mon, 17 Jul 2017 19:08:23 -0700 Subject: [PATCH 6/9] examples/addsvc2: rename to examples/addsvc --- examples/addsvc/client/grpc/client.go | 75 -- examples/addsvc/client/http/client.go | 86 -- examples/addsvc/client/thrift/client.go | 55 -- .../{addsvc2 => addsvc}/cmd/addcli/addcli.go | 6 +- examples/addsvc/cmd/addcli/main.go | 201 ----- .../{addsvc2 => addsvc}/cmd/addsvc/addsvc.go | 10 +- examples/addsvc/cmd/addsvc/main.go | 280 ------ .../cmd/addsvc/pact_test.go | 0 .../cmd/addsvc/wiring_test.go | 6 +- examples/addsvc/doc.go | 5 - examples/addsvc/endpoints.go | 134 --- examples/addsvc/pb/addsvc.pb.go | 61 +- .../pkg/addendpoint/middleware.go | 0 .../pkg/addendpoint/set.go | 2 +- .../pkg/addservice/middleware.go | 0 .../pkg/addservice/service.go | 0 .../pkg/addtransport/grpc.go | 6 +- .../pkg/addtransport/http.go | 4 +- .../pkg/addtransport/thrift.go | 22 +- examples/addsvc/service.go | 163 ---- examples/addsvc/transport_grpc.go | 118 --- examples/addsvc/transport_http.go | 130 --- examples/addsvc/transport_thrift.go | 73 -- examples/addsvc2/pb/addsvc.pb.go | 270 ------ examples/addsvc2/pb/addsvc.proto | 36 - examples/addsvc2/pb/compile.sh | 14 - examples/addsvc2/thrift/addsvc.thrift | 14 - examples/addsvc2/thrift/compile.sh | 5 - .../add_service-remote/add_service-remote.go | 157 ---- .../thrift/gen-go/addsvc/addservice.go | 807 ------------------ .../addsvc2/thrift/gen-go/addsvc/constants.go | 18 - .../addsvc2/thrift/gen-go/addsvc/ttypes.go | 269 ------ 32 files changed, 86 insertions(+), 2941 deletions(-) delete mode 100644 examples/addsvc/client/grpc/client.go delete mode 100644 examples/addsvc/client/http/client.go delete mode 100644 examples/addsvc/client/thrift/client.go rename examples/{addsvc2 => addsvc}/cmd/addcli/addcli.go (97%) delete mode 100644 examples/addsvc/cmd/addcli/main.go rename examples/{addsvc2 => addsvc}/cmd/addsvc/addsvc.go (97%) delete mode 100644 examples/addsvc/cmd/addsvc/main.go rename examples/{addsvc2 => addsvc}/cmd/addsvc/pact_test.go (100%) rename examples/{addsvc2 => addsvc}/cmd/addsvc/wiring_test.go (86%) delete mode 100644 examples/addsvc/doc.go delete mode 100644 examples/addsvc/endpoints.go rename examples/{addsvc2 => addsvc}/pkg/addendpoint/middleware.go (100%) rename examples/{addsvc2 => addsvc}/pkg/addendpoint/set.go (98%) rename examples/{addsvc2 => addsvc}/pkg/addservice/middleware.go (100%) rename examples/{addsvc2 => addsvc}/pkg/addservice/service.go (100%) rename examples/{addsvc2 => addsvc}/pkg/addtransport/grpc.go (97%) rename examples/{addsvc2 => addsvc}/pkg/addtransport/http.go (98%) rename examples/{addsvc2 => addsvc}/pkg/addtransport/thrift.go (85%) delete mode 100644 examples/addsvc/service.go delete mode 100644 examples/addsvc/transport_grpc.go delete mode 100644 examples/addsvc/transport_http.go delete mode 100644 examples/addsvc/transport_thrift.go delete mode 100644 examples/addsvc2/pb/addsvc.pb.go delete mode 100644 examples/addsvc2/pb/addsvc.proto delete mode 100755 examples/addsvc2/pb/compile.sh delete mode 100644 examples/addsvc2/thrift/addsvc.thrift delete mode 100755 examples/addsvc2/thrift/compile.sh delete mode 100755 examples/addsvc2/thrift/gen-go/addsvc/add_service-remote/add_service-remote.go delete mode 100644 examples/addsvc2/thrift/gen-go/addsvc/addservice.go delete mode 100644 examples/addsvc2/thrift/gen-go/addsvc/constants.go delete mode 100644 examples/addsvc2/thrift/gen-go/addsvc/ttypes.go diff --git a/examples/addsvc/client/grpc/client.go b/examples/addsvc/client/grpc/client.go deleted file mode 100644 index 2abcdae27..000000000 --- a/examples/addsvc/client/grpc/client.go +++ /dev/null @@ -1,75 +0,0 @@ -// Package grpc provides a gRPC client for the add service. -package grpc - -import ( - "time" - - jujuratelimit "github.com/juju/ratelimit" - stdopentracing "github.com/opentracing/opentracing-go" - "github.com/sony/gobreaker" - "google.golang.org/grpc" - - "github.com/go-kit/kit/circuitbreaker" - "github.com/go-kit/kit/endpoint" - "github.com/go-kit/kit/examples/addsvc" - "github.com/go-kit/kit/examples/addsvc/pb" - "github.com/go-kit/kit/log" - "github.com/go-kit/kit/ratelimit" - "github.com/go-kit/kit/tracing/opentracing" - grpctransport "github.com/go-kit/kit/transport/grpc" -) - -// New returns an AddService backed by a gRPC client connection. It is the -// responsibility of the caller to dial, and later close, the connection. -func New(conn *grpc.ClientConn, tracer stdopentracing.Tracer, logger log.Logger) addsvc.Service { - // We construct a single ratelimiter middleware, to limit the total outgoing - // QPS from this client to all methods on the remote instance. We also - // construct per-endpoint circuitbreaker middlewares to demonstrate how - // that's done, although they could easily be combined into a single breaker - // for the entire remote instance, too. - - limiter := ratelimit.NewTokenBucketLimiter(jujuratelimit.NewBucketWithRate(100, 100)) - - var sumEndpoint endpoint.Endpoint - { - sumEndpoint = grpctransport.NewClient( - conn, - "pb.Add", - "Sum", - addsvc.EncodeGRPCSumRequest, - addsvc.DecodeGRPCSumResponse, - pb.SumReply{}, - grpctransport.ClientBefore(opentracing.ToGRPCRequest(tracer, logger)), - ).Endpoint() - sumEndpoint = opentracing.TraceClient(tracer, "Sum")(sumEndpoint) - sumEndpoint = limiter(sumEndpoint) - sumEndpoint = circuitbreaker.Gobreaker(gobreaker.NewCircuitBreaker(gobreaker.Settings{ - Name: "Sum", - Timeout: 30 * time.Second, - }))(sumEndpoint) - } - - var concatEndpoint endpoint.Endpoint - { - concatEndpoint = grpctransport.NewClient( - conn, - "pb.Add", - "Concat", - addsvc.EncodeGRPCConcatRequest, - addsvc.DecodeGRPCConcatResponse, - pb.ConcatReply{}, - grpctransport.ClientBefore(opentracing.ToGRPCRequest(tracer, logger)), - ).Endpoint() - concatEndpoint = opentracing.TraceClient(tracer, "Concat")(concatEndpoint) - concatEndpoint = limiter(concatEndpoint) - concatEndpoint = circuitbreaker.Gobreaker(gobreaker.NewCircuitBreaker(gobreaker.Settings{ - Name: "Concat", - Timeout: 30 * time.Second, - }))(concatEndpoint) - } - - return addsvc.Endpoints{ - SumEndpoint: sumEndpoint, - ConcatEndpoint: concatEndpoint, - } -} diff --git a/examples/addsvc/client/http/client.go b/examples/addsvc/client/http/client.go deleted file mode 100644 index be8d8e24d..000000000 --- a/examples/addsvc/client/http/client.go +++ /dev/null @@ -1,86 +0,0 @@ -// Package http provides an HTTP client for the add service. -package http - -import ( - "net/url" - "strings" - "time" - - jujuratelimit "github.com/juju/ratelimit" - stdopentracing "github.com/opentracing/opentracing-go" - "github.com/sony/gobreaker" - - "github.com/go-kit/kit/circuitbreaker" - "github.com/go-kit/kit/endpoint" - "github.com/go-kit/kit/examples/addsvc" - "github.com/go-kit/kit/log" - "github.com/go-kit/kit/ratelimit" - "github.com/go-kit/kit/tracing/opentracing" - httptransport "github.com/go-kit/kit/transport/http" -) - -// New returns an AddService backed by an HTTP server living at the remote -// instance. We expect instance to come from a service discovery system, so -// likely of the form "host:port". -func New(instance string, tracer stdopentracing.Tracer, logger log.Logger) (addsvc.Service, error) { - if !strings.HasPrefix(instance, "http") { - instance = "http://" + instance - } - u, err := url.Parse(instance) - if err != nil { - return nil, err - } - - // We construct a single ratelimiter middleware, to limit the total outgoing - // QPS from this client to all methods on the remote instance. We also - // construct per-endpoint circuitbreaker middlewares to demonstrate how - // that's done, although they could easily be combined into a single breaker - // for the entire remote instance, too. - - limiter := ratelimit.NewTokenBucketLimiter(jujuratelimit.NewBucketWithRate(100, 100)) - - var sumEndpoint endpoint.Endpoint - { - sumEndpoint = httptransport.NewClient( - "POST", - copyURL(u, "/sum"), - addsvc.EncodeHTTPGenericRequest, - addsvc.DecodeHTTPSumResponse, - httptransport.ClientBefore(opentracing.ToHTTPRequest(tracer, logger)), - ).Endpoint() - sumEndpoint = opentracing.TraceClient(tracer, "Sum")(sumEndpoint) - sumEndpoint = limiter(sumEndpoint) - sumEndpoint = circuitbreaker.Gobreaker(gobreaker.NewCircuitBreaker(gobreaker.Settings{ - Name: "Sum", - Timeout: 30 * time.Second, - }))(sumEndpoint) - } - - var concatEndpoint endpoint.Endpoint - { - concatEndpoint = httptransport.NewClient( - "POST", - copyURL(u, "/concat"), - addsvc.EncodeHTTPGenericRequest, - addsvc.DecodeHTTPConcatResponse, - httptransport.ClientBefore(opentracing.ToHTTPRequest(tracer, logger)), - ).Endpoint() - concatEndpoint = opentracing.TraceClient(tracer, "Concat")(concatEndpoint) - concatEndpoint = limiter(concatEndpoint) - concatEndpoint = circuitbreaker.Gobreaker(gobreaker.NewCircuitBreaker(gobreaker.Settings{ - Name: "Concat", - Timeout: 30 * time.Second, - }))(concatEndpoint) - } - - return addsvc.Endpoints{ - SumEndpoint: sumEndpoint, - ConcatEndpoint: concatEndpoint, - }, nil -} - -func copyURL(base *url.URL, path string) *url.URL { - next := *base - next.Path = path - return &next -} diff --git a/examples/addsvc/client/thrift/client.go b/examples/addsvc/client/thrift/client.go deleted file mode 100644 index 4463ae843..000000000 --- a/examples/addsvc/client/thrift/client.go +++ /dev/null @@ -1,55 +0,0 @@ -// Package thrift provides a Thrift client for the add service. -package thrift - -import ( - "time" - - jujuratelimit "github.com/juju/ratelimit" - "github.com/sony/gobreaker" - - "github.com/go-kit/kit/circuitbreaker" - "github.com/go-kit/kit/endpoint" - "github.com/go-kit/kit/examples/addsvc" - thriftadd "github.com/go-kit/kit/examples/addsvc/thrift/gen-go/addsvc" - "github.com/go-kit/kit/ratelimit" -) - -// New returns an AddService backed by a Thrift server described by the provided -// client. The caller is responsible for constructing the client, and eventually -// closing the underlying transport. -func New(client *thriftadd.AddServiceClient) addsvc.Service { - // We construct a single ratelimiter middleware, to limit the total outgoing - // QPS from this client to all methods on the remote instance. We also - // construct per-endpoint circuitbreaker middlewares to demonstrate how - // that's done, although they could easily be combined into a single breaker - // for the entire remote instance, too. - - limiter := ratelimit.NewTokenBucketLimiter(jujuratelimit.NewBucketWithRate(100, 100)) - - // Thrift does not currently have tracer bindings, so we skip tracing. - - var sumEndpoint endpoint.Endpoint - { - sumEndpoint = addsvc.MakeThriftSumEndpoint(client) - sumEndpoint = limiter(sumEndpoint) - sumEndpoint = circuitbreaker.Gobreaker(gobreaker.NewCircuitBreaker(gobreaker.Settings{ - Name: "Sum", - Timeout: 30 * time.Second, - }))(sumEndpoint) - } - - var concatEndpoint endpoint.Endpoint - { - concatEndpoint = addsvc.MakeThriftConcatEndpoint(client) - concatEndpoint = limiter(concatEndpoint) - concatEndpoint = circuitbreaker.Gobreaker(gobreaker.NewCircuitBreaker(gobreaker.Settings{ - Name: "Concat", - Timeout: 30 * time.Second, - }))(concatEndpoint) - } - - return addsvc.Endpoints{ - SumEndpoint: sumEndpoint, - ConcatEndpoint: concatEndpoint, - } -} diff --git a/examples/addsvc2/cmd/addcli/addcli.go b/examples/addsvc/cmd/addcli/addcli.go similarity index 97% rename from examples/addsvc2/cmd/addcli/addcli.go rename to examples/addsvc/cmd/addcli/addcli.go index 7af3ce0e7..e2f0f94d0 100644 --- a/examples/addsvc2/cmd/addcli/addcli.go +++ b/examples/addsvc/cmd/addcli/addcli.go @@ -20,9 +20,9 @@ import ( "github.com/go-kit/kit/log" - "github.com/go-kit/kit/examples/addsvc2/pkg/addservice" - "github.com/go-kit/kit/examples/addsvc2/pkg/addtransport" - addthrift "github.com/go-kit/kit/examples/addsvc2/thrift/gen-go/addsvc" + "github.com/go-kit/kit/examples/addsvc/pkg/addservice" + "github.com/go-kit/kit/examples/addsvc/pkg/addtransport" + addthrift "github.com/go-kit/kit/examples/addsvc/thrift/gen-go/addsvc" ) func main() { diff --git a/examples/addsvc/cmd/addcli/main.go b/examples/addsvc/cmd/addcli/main.go deleted file mode 100644 index c3a861d96..000000000 --- a/examples/addsvc/cmd/addcli/main.go +++ /dev/null @@ -1,201 +0,0 @@ -package main - -import ( - "context" - "flag" - "fmt" - "os" - "strconv" - "strings" - "time" - - "github.com/apache/thrift/lib/go/thrift" - "github.com/lightstep/lightstep-tracer-go" - stdopentracing "github.com/opentracing/opentracing-go" - zipkin "github.com/openzipkin/zipkin-go-opentracing" - "google.golang.org/grpc" - "sourcegraph.com/sourcegraph/appdash" - appdashot "sourcegraph.com/sourcegraph/appdash/opentracing" - - "github.com/go-kit/kit/examples/addsvc" - grpcclient "github.com/go-kit/kit/examples/addsvc/client/grpc" - httpclient "github.com/go-kit/kit/examples/addsvc/client/http" - thriftclient "github.com/go-kit/kit/examples/addsvc/client/thrift" - thriftadd "github.com/go-kit/kit/examples/addsvc/thrift/gen-go/addsvc" - "github.com/go-kit/kit/log" -) - -func main() { - // The addcli presumes no service discovery system, and expects users to - // provide the direct address of an addsvc. This presumption is reflected in - // the addcli binary and the the client packages: the -transport.addr flags - // and various client constructors both expect host:port strings. For an - // example service with a client built on top of a service discovery system, - // see profilesvc. - - var ( - httpAddr = flag.String("http.addr", "", "HTTP address of addsvc") - grpcAddr = flag.String("grpc.addr", "", "gRPC (HTTP) address of addsvc") - thriftAddr = flag.String("thrift.addr", "", "Thrift address of addsvc") - thriftProtocol = flag.String("thrift.protocol", "binary", "binary, compact, json, simplejson") - thriftBufferSize = flag.Int("thrift.buffer.size", 0, "0 for unbuffered") - thriftFramed = flag.Bool("thrift.framed", false, "true to enable framing") - zipkinAddr = flag.String("zipkin.addr", "", "Enable Zipkin tracing via a Zipkin HTTP Collector endpoint") - zipkinKafkaAddr = flag.String("zipkin.kafka.addr", "", "Enable Zipkin tracing via a Kafka server host:port") - appdashAddr = flag.String("appdash.addr", "", "Enable Appdash tracing via an Appdash server host:port") - lightstepToken = flag.String("lightstep.token", "", "Enable LightStep tracing via a LightStep access token") - method = flag.String("method", "sum", "sum, concat") - ) - flag.Parse() - - if len(flag.Args()) != 2 { - fmt.Fprintf(os.Stderr, "usage: addcli [flags] \n") - os.Exit(1) - } - - // This is a demonstration client, which supports multiple tracers. - // Your clients will probably just use one tracer. - var tracer stdopentracing.Tracer - { - if *zipkinAddr != "" { - // endpoint typically looks like: http://zipkinhost:9411/api/v1/spans - collector, err := zipkin.NewHTTPCollector(*zipkinAddr) - if err != nil { - fmt.Fprintf(os.Stderr, "%v\n", err) - os.Exit(1) - } - defer collector.Close() - - tracer, err = zipkin.NewTracer( - zipkin.NewRecorder(collector, false, "0.0.0.0:0", "addcli"), - ) - if err != nil { - fmt.Fprintf(os.Stderr, "%v\n", err) - os.Exit(1) - } - } else if *zipkinKafkaAddr != "" { - collector, err := zipkin.NewKafkaCollector( - strings.Split(*zipkinKafkaAddr, ","), - zipkin.KafkaLogger(log.NewNopLogger()), - ) - if err != nil { - fmt.Fprintf(os.Stderr, "%v\n", err) - os.Exit(1) - } - defer collector.Close() - - tracer, err = zipkin.NewTracer( - zipkin.NewRecorder(collector, false, "0.0.0.0:0", "addcli"), - ) - if err != nil { - fmt.Fprintf(os.Stderr, "%v\n", err) - os.Exit(1) - } - } else if *appdashAddr != "" { - tracer = appdashot.NewTracer(appdash.NewRemoteCollector(*appdashAddr)) - } else if *lightstepToken != "" { - tracer = lightstep.NewTracer(lightstep.Options{ - AccessToken: *lightstepToken, - }) - defer lightstep.FlushLightStepTracer(tracer) - } else { - tracer = stdopentracing.GlobalTracer() // no-op - } - } - - // This is a demonstration client, which supports multiple transports. - // Your clients will probably just define and stick with 1 transport. - - var ( - service addsvc.Service - err error - ) - if *httpAddr != "" { - service, err = httpclient.New(*httpAddr, tracer, log.NewNopLogger()) - } else if *grpcAddr != "" { - conn, err := grpc.Dial(*grpcAddr, grpc.WithInsecure(), grpc.WithTimeout(time.Second)) - if err != nil { - fmt.Fprintf(os.Stderr, "error: %v", err) - os.Exit(1) - } - defer conn.Close() - service = grpcclient.New(conn, tracer, log.NewNopLogger()) - } else if *thriftAddr != "" { - // It's necessary to do all of this construction in the func main, - // because (among other reasons) we need to control the lifecycle of the - // Thrift transport, i.e. close it eventually. - var protocolFactory thrift.TProtocolFactory - switch *thriftProtocol { - case "compact": - protocolFactory = thrift.NewTCompactProtocolFactory() - case "simplejson": - protocolFactory = thrift.NewTSimpleJSONProtocolFactory() - case "json": - protocolFactory = thrift.NewTJSONProtocolFactory() - case "binary", "": - protocolFactory = thrift.NewTBinaryProtocolFactoryDefault() - default: - fmt.Fprintf(os.Stderr, "error: invalid protocol %q\n", *thriftProtocol) - os.Exit(1) - } - var transportFactory thrift.TTransportFactory - if *thriftBufferSize > 0 { - transportFactory = thrift.NewTBufferedTransportFactory(*thriftBufferSize) - } else { - transportFactory = thrift.NewTTransportFactory() - } - if *thriftFramed { - transportFactory = thrift.NewTFramedTransportFactory(transportFactory) - } - transportSocket, err := thrift.NewTSocket(*thriftAddr) - if err != nil { - fmt.Fprintf(os.Stderr, "error: %v\n", err) - os.Exit(1) - } - transport, err := transportFactory.GetTransport(transportSocket) - if err != nil { - fmt.Fprintf(os.Stderr, "error: %v\n", err) - os.Exit(1) - } - if err := transport.Open(); err != nil { - fmt.Fprintf(os.Stderr, "error: %v\n", err) - os.Exit(1) - } - defer transport.Close() - client := thriftadd.NewAddServiceClientFactory(transport, protocolFactory) - service = thriftclient.New(client) - } else { - fmt.Fprintf(os.Stderr, "error: no remote address specified\n") - os.Exit(1) - } - if err != nil { - fmt.Fprintf(os.Stderr, "error: %v\n", err) - os.Exit(1) - } - - switch *method { - case "sum": - a, _ := strconv.ParseInt(flag.Args()[0], 10, 64) - b, _ := strconv.ParseInt(flag.Args()[1], 10, 64) - v, err := service.Sum(context.Background(), int(a), int(b)) - if err != nil { - fmt.Fprintf(os.Stderr, "error: %v\n", err) - os.Exit(1) - } - fmt.Fprintf(os.Stdout, "%d + %d = %d\n", a, b, v) - - case "concat": - a := flag.Args()[0] - b := flag.Args()[1] - v, err := service.Concat(context.Background(), a, b) - if err != nil { - fmt.Fprintf(os.Stderr, "error: %v\n", err) - os.Exit(1) - } - fmt.Fprintf(os.Stdout, "%q + %q = %q\n", a, b, v) - - default: - fmt.Fprintf(os.Stderr, "error: invalid method %q\n", method) - os.Exit(1) - } -} diff --git a/examples/addsvc2/cmd/addsvc/addsvc.go b/examples/addsvc/cmd/addsvc/addsvc.go similarity index 97% rename from examples/addsvc2/cmd/addsvc/addsvc.go rename to examples/addsvc/cmd/addsvc/addsvc.go index f5dc077cd..eedaf0722 100644 --- a/examples/addsvc2/cmd/addsvc/addsvc.go +++ b/examples/addsvc/cmd/addsvc/addsvc.go @@ -26,11 +26,11 @@ import ( "github.com/go-kit/kit/metrics" "github.com/go-kit/kit/metrics/prometheus" - addpb "github.com/go-kit/kit/examples/addsvc2/pb" - "github.com/go-kit/kit/examples/addsvc2/pkg/addendpoint" - "github.com/go-kit/kit/examples/addsvc2/pkg/addservice" - "github.com/go-kit/kit/examples/addsvc2/pkg/addtransport" - addthrift "github.com/go-kit/kit/examples/addsvc2/thrift/gen-go/addsvc" + addpb "github.com/go-kit/kit/examples/addsvc/pb" + "github.com/go-kit/kit/examples/addsvc/pkg/addendpoint" + "github.com/go-kit/kit/examples/addsvc/pkg/addservice" + "github.com/go-kit/kit/examples/addsvc/pkg/addtransport" + addthrift "github.com/go-kit/kit/examples/addsvc/thrift/gen-go/addsvc" ) func main() { diff --git a/examples/addsvc/cmd/addsvc/main.go b/examples/addsvc/cmd/addsvc/main.go deleted file mode 100644 index 722f9efa5..000000000 --- a/examples/addsvc/cmd/addsvc/main.go +++ /dev/null @@ -1,280 +0,0 @@ -package main - -import ( - "context" - "flag" - "fmt" - "net" - "net/http" - "net/http/pprof" - "os" - "os/signal" - "strings" - "syscall" - - "github.com/apache/thrift/lib/go/thrift" - lightstep "github.com/lightstep/lightstep-tracer-go" - stdopentracing "github.com/opentracing/opentracing-go" - zipkin "github.com/openzipkin/zipkin-go-opentracing" - stdprometheus "github.com/prometheus/client_golang/prometheus" - "github.com/prometheus/client_golang/prometheus/promhttp" - "google.golang.org/grpc" - "sourcegraph.com/sourcegraph/appdash" - appdashot "sourcegraph.com/sourcegraph/appdash/opentracing" - - "github.com/go-kit/kit/endpoint" - "github.com/go-kit/kit/examples/addsvc" - "github.com/go-kit/kit/examples/addsvc/pb" - thriftadd "github.com/go-kit/kit/examples/addsvc/thrift/gen-go/addsvc" - "github.com/go-kit/kit/log" - "github.com/go-kit/kit/metrics" - "github.com/go-kit/kit/metrics/prometheus" - "github.com/go-kit/kit/tracing/opentracing" -) - -func main() { - var ( - debugAddr = flag.String("debug.addr", ":8080", "Debug and metrics listen address") - httpAddr = flag.String("http.addr", ":8081", "HTTP listen address") - grpcAddr = flag.String("grpc.addr", ":8082", "gRPC (HTTP) listen address") - thriftAddr = flag.String("thrift.addr", ":8083", "Thrift listen address") - thriftProtocol = flag.String("thrift.protocol", "binary", "binary, compact, json, simplejson") - thriftBufferSize = flag.Int("thrift.buffer.size", 0, "0 for unbuffered") - thriftFramed = flag.Bool("thrift.framed", false, "true to enable framing") - zipkinAddr = flag.String("zipkin.addr", "", "Enable Zipkin tracing via a Zipkin HTTP Collector endpoint") - zipkinKafkaAddr = flag.String("zipkin.kafka.addr", "", "Enable Zipkin tracing via a Kafka server host:port") - appdashAddr = flag.String("appdash.addr", "", "Enable Appdash tracing via an Appdash server host:port") - lightstepToken = flag.String("lightstep.token", "", "Enable LightStep tracing via a LightStep access token") - ) - flag.Parse() - - // Logging domain. - var logger log.Logger - { - logger = log.NewLogfmtLogger(os.Stdout) - logger = log.With(logger, "ts", log.DefaultTimestampUTC) - logger = log.With(logger, "caller", log.DefaultCaller) - } - logger.Log("msg", "hello") - defer logger.Log("msg", "goodbye") - - // Metrics domain. - var ints, chars metrics.Counter - { - // Business level metrics. - ints = prometheus.NewCounterFrom(stdprometheus.CounterOpts{ - Namespace: "addsvc", - Name: "integers_summed", - Help: "Total count of integers summed via the Sum method.", - }, []string{}) - chars = prometheus.NewCounterFrom(stdprometheus.CounterOpts{ - Namespace: "addsvc", - Name: "characters_concatenated", - Help: "Total count of characters concatenated via the Concat method.", - }, []string{}) - } - var duration metrics.Histogram - { - // Transport level metrics. - duration = prometheus.NewSummaryFrom(stdprometheus.SummaryOpts{ - Namespace: "addsvc", - Name: "request_duration_ns", - Help: "Request duration in nanoseconds.", - }, []string{"method", "success"}) - } - - // Tracing domain. - var tracer stdopentracing.Tracer - { - if *zipkinAddr != "" { - logger := log.With(logger, "tracer", "ZipkinHTTP") - logger.Log("addr", *zipkinAddr) - - // endpoint typically looks like: http://zipkinhost:9411/api/v1/spans - collector, err := zipkin.NewHTTPCollector(*zipkinAddr) - if err != nil { - logger.Log("err", err) - os.Exit(1) - } - defer collector.Close() - - tracer, err = zipkin.NewTracer( - zipkin.NewRecorder(collector, false, "localhost:80", "addsvc"), - ) - if err != nil { - logger.Log("err", err) - os.Exit(1) - } - } else if *zipkinKafkaAddr != "" { - logger := log.With(logger, "tracer", "ZipkinKafka") - logger.Log("addr", *zipkinKafkaAddr) - - collector, err := zipkin.NewKafkaCollector( - strings.Split(*zipkinKafkaAddr, ","), - zipkin.KafkaLogger(log.NewNopLogger()), - ) - if err != nil { - logger.Log("err", err) - os.Exit(1) - } - defer collector.Close() - - tracer, err = zipkin.NewTracer( - zipkin.NewRecorder(collector, false, "localhost:80", "addsvc"), - ) - if err != nil { - logger.Log("err", err) - os.Exit(1) - } - } else if *appdashAddr != "" { - logger := log.With(logger, "tracer", "Appdash") - logger.Log("addr", *appdashAddr) - tracer = appdashot.NewTracer(appdash.NewRemoteCollector(*appdashAddr)) - } else if *lightstepToken != "" { - logger := log.With(logger, "tracer", "LightStep") - logger.Log() // probably don't want to print out the token :) - tracer = lightstep.NewTracer(lightstep.Options{ - AccessToken: *lightstepToken, - }) - defer lightstep.FlushLightStepTracer(tracer) - } else { - logger := log.With(logger, "tracer", "none") - logger.Log() - tracer = stdopentracing.GlobalTracer() // no-op - } - } - - // Business domain. - var service addsvc.Service - { - service = addsvc.NewBasicService() - service = addsvc.ServiceLoggingMiddleware(logger)(service) - service = addsvc.ServiceInstrumentingMiddleware(ints, chars)(service) - } - - // Endpoint domain. - var sumEndpoint endpoint.Endpoint - { - sumDuration := duration.With("method", "Sum") - sumLogger := log.With(logger, "method", "Sum") - - sumEndpoint = addsvc.MakeSumEndpoint(service) - sumEndpoint = opentracing.TraceServer(tracer, "Sum")(sumEndpoint) - sumEndpoint = addsvc.EndpointInstrumentingMiddleware(sumDuration)(sumEndpoint) - sumEndpoint = addsvc.EndpointLoggingMiddleware(sumLogger)(sumEndpoint) - } - var concatEndpoint endpoint.Endpoint - { - concatDuration := duration.With("method", "Concat") - concatLogger := log.With(logger, "method", "Concat") - - concatEndpoint = addsvc.MakeConcatEndpoint(service) - concatEndpoint = opentracing.TraceServer(tracer, "Concat")(concatEndpoint) - concatEndpoint = addsvc.EndpointInstrumentingMiddleware(concatDuration)(concatEndpoint) - concatEndpoint = addsvc.EndpointLoggingMiddleware(concatLogger)(concatEndpoint) - } - endpoints := addsvc.Endpoints{ - SumEndpoint: sumEndpoint, - ConcatEndpoint: concatEndpoint, - } - - // Mechanical domain. - errc := make(chan error) - ctx := context.Background() - - // Interrupt handler. - go func() { - c := make(chan os.Signal, 1) - signal.Notify(c, syscall.SIGINT, syscall.SIGTERM) - errc <- fmt.Errorf("%s", <-c) - }() - - // Debug listener. - go func() { - logger := log.With(logger, "transport", "debug") - - m := http.NewServeMux() - m.Handle("/debug/pprof/", http.HandlerFunc(pprof.Index)) - m.Handle("/debug/pprof/cmdline", http.HandlerFunc(pprof.Cmdline)) - m.Handle("/debug/pprof/profile", http.HandlerFunc(pprof.Profile)) - m.Handle("/debug/pprof/symbol", http.HandlerFunc(pprof.Symbol)) - m.Handle("/debug/pprof/trace", http.HandlerFunc(pprof.Trace)) - m.Handle("/metrics", promhttp.Handler()) - - logger.Log("addr", *debugAddr) - errc <- http.ListenAndServe(*debugAddr, m) - }() - - // HTTP transport. - go func() { - logger := log.With(logger, "transport", "HTTP") - h := addsvc.MakeHTTPHandler(endpoints, tracer, logger) - logger.Log("addr", *httpAddr) - errc <- http.ListenAndServe(*httpAddr, h) - }() - - // gRPC transport. - go func() { - logger := log.With(logger, "transport", "gRPC") - - ln, err := net.Listen("tcp", *grpcAddr) - if err != nil { - errc <- err - return - } - - srv := addsvc.MakeGRPCServer(endpoints, tracer, logger) - s := grpc.NewServer() - pb.RegisterAddServer(s, srv) - - logger.Log("addr", *grpcAddr) - errc <- s.Serve(ln) - }() - - // Thrift transport. - go func() { - logger := log.With(logger, "transport", "Thrift") - - var protocolFactory thrift.TProtocolFactory - switch *thriftProtocol { - case "binary": - protocolFactory = thrift.NewTBinaryProtocolFactoryDefault() - case "compact": - protocolFactory = thrift.NewTCompactProtocolFactory() - case "json": - protocolFactory = thrift.NewTJSONProtocolFactory() - case "simplejson": - protocolFactory = thrift.NewTSimpleJSONProtocolFactory() - default: - errc <- fmt.Errorf("invalid Thrift protocol %q", *thriftProtocol) - return - } - - var transportFactory thrift.TTransportFactory - if *thriftBufferSize > 0 { - transportFactory = thrift.NewTBufferedTransportFactory(*thriftBufferSize) - } else { - transportFactory = thrift.NewTTransportFactory() - } - if *thriftFramed { - transportFactory = thrift.NewTFramedTransportFactory(transportFactory) - } - - transport, err := thrift.NewTServerSocket(*thriftAddr) - if err != nil { - errc <- err - return - } - - logger.Log("addr", *thriftAddr) - errc <- thrift.NewTSimpleServer4( - thriftadd.NewAddServiceProcessor(addsvc.MakeThriftHandler(ctx, endpoints)), - transport, - transportFactory, - protocolFactory, - ).Serve() - }() - - // Run! - logger.Log("exit", <-errc) -} diff --git a/examples/addsvc2/cmd/addsvc/pact_test.go b/examples/addsvc/cmd/addsvc/pact_test.go similarity index 100% rename from examples/addsvc2/cmd/addsvc/pact_test.go rename to examples/addsvc/cmd/addsvc/pact_test.go diff --git a/examples/addsvc2/cmd/addsvc/wiring_test.go b/examples/addsvc/cmd/addsvc/wiring_test.go similarity index 86% rename from examples/addsvc2/cmd/addsvc/wiring_test.go rename to examples/addsvc/cmd/addsvc/wiring_test.go index fb3dbe0d0..ca64bac1f 100644 --- a/examples/addsvc2/cmd/addsvc/wiring_test.go +++ b/examples/addsvc/cmd/addsvc/wiring_test.go @@ -12,9 +12,9 @@ import ( "github.com/go-kit/kit/log" "github.com/go-kit/kit/metrics/discard" - "github.com/go-kit/kit/examples/addsvc2/pkg/addendpoint" - "github.com/go-kit/kit/examples/addsvc2/pkg/addservice" - "github.com/go-kit/kit/examples/addsvc2/pkg/addtransport" + "github.com/go-kit/kit/examples/addsvc/pkg/addendpoint" + "github.com/go-kit/kit/examples/addsvc/pkg/addservice" + "github.com/go-kit/kit/examples/addsvc/pkg/addtransport" ) func TestHTTP(t *testing.T) { diff --git a/examples/addsvc/doc.go b/examples/addsvc/doc.go deleted file mode 100644 index 584d072cb..000000000 --- a/examples/addsvc/doc.go +++ /dev/null @@ -1,5 +0,0 @@ -// Package addsvc is an example microservice, useful for education. It can sum -// integers and concatenate strings. A client library is available in the client -// subdirectory. A server binary is available in cmd/addsvc. An example client -// binary is available in cmd/addcli. -package addsvc diff --git a/examples/addsvc/endpoints.go b/examples/addsvc/endpoints.go deleted file mode 100644 index 1da33e41c..000000000 --- a/examples/addsvc/endpoints.go +++ /dev/null @@ -1,134 +0,0 @@ -package addsvc - -// This file contains methods to make individual endpoints from services, -// request and response types to serve those endpoints, as well as encoders and -// decoders for those types, for all of our supported transport serialization -// formats. It also includes endpoint middlewares. - -import ( - "context" - "fmt" - "time" - - "github.com/go-kit/kit/endpoint" - "github.com/go-kit/kit/log" - "github.com/go-kit/kit/metrics" -) - -// Endpoints collects all of the endpoints that compose an add service. It's -// meant to be used as a helper struct, to collect all of the endpoints into a -// single parameter. -// -// In a server, it's useful for functions that need to operate on a per-endpoint -// basis. For example, you might pass an Endpoints to a function that produces -// an http.Handler, with each method (endpoint) wired up to a specific path. (It -// is probably a mistake in design to invoke the Service methods on the -// Endpoints struct in a server.) -// -// In a client, it's useful to collect individually constructed endpoints into a -// single type that implements the Service interface. For example, you might -// construct individual endpoints using transport/http.NewClient, combine them -// into an Endpoints, and return it to the caller as a Service. -type Endpoints struct { - SumEndpoint endpoint.Endpoint - ConcatEndpoint endpoint.Endpoint -} - -// Sum implements Service. Primarily useful in a client. -func (e Endpoints) Sum(ctx context.Context, a, b int) (int, error) { - request := sumRequest{A: a, B: b} - response, err := e.SumEndpoint(ctx, request) - if err != nil { - return 0, err - } - return response.(sumResponse).V, response.(sumResponse).Err -} - -// Concat implements Service. Primarily useful in a client. -func (e Endpoints) Concat(ctx context.Context, a, b string) (string, error) { - request := concatRequest{A: a, B: b} - response, err := e.ConcatEndpoint(ctx, request) - if err != nil { - return "", err - } - return response.(concatResponse).V, response.(concatResponse).Err -} - -// MakeSumEndpoint returns an endpoint that invokes Sum on the service. -// Primarily useful in a server. -func MakeSumEndpoint(s Service) endpoint.Endpoint { - return func(ctx context.Context, request interface{}) (response interface{}, err error) { - sumReq := request.(sumRequest) - v, err := s.Sum(ctx, sumReq.A, sumReq.B) - if err == ErrIntOverflow { - return nil, err // special case; see comment on ErrIntOverflow - } - return sumResponse{ - V: v, - Err: err, - }, nil - } -} - -// MakeConcatEndpoint returns an endpoint that invokes Concat on the service. -// Primarily useful in a server. -func MakeConcatEndpoint(s Service) endpoint.Endpoint { - return func(ctx context.Context, request interface{}) (response interface{}, err error) { - concatReq := request.(concatRequest) - v, err := s.Concat(ctx, concatReq.A, concatReq.B) - return concatResponse{ - V: v, - Err: err, - }, nil - } -} - -// EndpointInstrumentingMiddleware returns an endpoint middleware that records -// the duration of each invocation to the passed histogram. The middleware adds -// a single field: "success", which is "true" if no error is returned, and -// "false" otherwise. -func EndpointInstrumentingMiddleware(duration metrics.Histogram) endpoint.Middleware { - return func(next endpoint.Endpoint) endpoint.Endpoint { - return func(ctx context.Context, request interface{}) (response interface{}, err error) { - - defer func(begin time.Time) { - duration.With("success", fmt.Sprint(err == nil)).Observe(time.Since(begin).Seconds()) - }(time.Now()) - return next(ctx, request) - - } - } -} - -// EndpointLoggingMiddleware returns an endpoint middleware that logs the -// duration of each invocation, and the resulting error, if any. -func EndpointLoggingMiddleware(logger log.Logger) endpoint.Middleware { - return func(next endpoint.Endpoint) endpoint.Endpoint { - return func(ctx context.Context, request interface{}) (response interface{}, err error) { - - defer func(begin time.Time) { - logger.Log("error", err, "took", time.Since(begin)) - }(time.Now()) - return next(ctx, request) - - } - } -} - -// These types are unexported because they only exist to serve the endpoint -// domain, which is totally encapsulated in this package. They are otherwise -// opaque to all callers. - -type sumRequest struct{ A, B int } - -type sumResponse struct { - V int - Err error -} - -type concatRequest struct{ A, B string } - -type concatResponse struct { - V string - Err error -} diff --git a/examples/addsvc/pb/addsvc.pb.go b/examples/addsvc/pb/addsvc.pb.go index a685eef04..781b50b75 100644 --- a/examples/addsvc/pb/addsvc.pb.go +++ b/examples/addsvc/pb/addsvc.pb.go @@ -1,6 +1,5 @@ -// Code generated by protoc-gen-go. +// Code generated by protoc-gen-go. DO NOT EDIT. // source: addsvc.proto -// DO NOT EDIT! /* Package pb is a generated protocol buffer package. @@ -47,6 +46,20 @@ func (m *SumRequest) String() string { return proto.CompactTextString func (*SumRequest) ProtoMessage() {} func (*SumRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} } +func (m *SumRequest) GetA() int64 { + if m != nil { + return m.A + } + return 0 +} + +func (m *SumRequest) GetB() int64 { + if m != nil { + return m.B + } + return 0 +} + // The sum response contains the result of the calculation. type SumReply struct { V int64 `protobuf:"varint,1,opt,name=v" json:"v,omitempty"` @@ -58,6 +71,20 @@ func (m *SumReply) String() string { return proto.CompactTextString(m func (*SumReply) ProtoMessage() {} func (*SumReply) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} } +func (m *SumReply) GetV() int64 { + if m != nil { + return m.V + } + return 0 +} + +func (m *SumReply) GetErr() string { + if m != nil { + return m.Err + } + return "" +} + // The Concat request contains two parameters. type ConcatRequest struct { A string `protobuf:"bytes,1,opt,name=a" json:"a,omitempty"` @@ -69,6 +96,20 @@ func (m *ConcatRequest) String() string { return proto.CompactTextStr func (*ConcatRequest) ProtoMessage() {} func (*ConcatRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2} } +func (m *ConcatRequest) GetA() string { + if m != nil { + return m.A + } + return "" +} + +func (m *ConcatRequest) GetB() string { + if m != nil { + return m.B + } + return "" +} + // The Concat response contains the result of the concatenation. type ConcatReply struct { V string `protobuf:"bytes,1,opt,name=v" json:"v,omitempty"` @@ -80,6 +121,20 @@ func (m *ConcatReply) String() string { return proto.CompactTextStrin func (*ConcatReply) ProtoMessage() {} func (*ConcatReply) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{3} } +func (m *ConcatReply) GetV() string { + if m != nil { + return m.V + } + return "" +} + +func (m *ConcatReply) GetErr() string { + if m != nil { + return m.Err + } + return "" +} + func init() { proto.RegisterType((*SumRequest)(nil), "pb.SumRequest") proto.RegisterType((*SumReply)(nil), "pb.SumReply") @@ -200,7 +255,7 @@ func init() { proto.RegisterFile("addsvc.proto", fileDescriptor0) } var fileDescriptor0 = []byte{ // 189 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xe2, 0xe2, 0x49, 0x4c, 0x49, 0x29, + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xe2, 0x49, 0x4c, 0x49, 0x29, 0x2e, 0x4b, 0xd6, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x62, 0x2a, 0x48, 0x52, 0xd2, 0xe0, 0xe2, 0x0a, 0x2e, 0xcd, 0x0d, 0x4a, 0x2d, 0x2c, 0x4d, 0x2d, 0x2e, 0x11, 0xe2, 0xe1, 0x62, 0x4c, 0x94, 0x60, 0x54, 0x60, 0xd4, 0x60, 0x0e, 0x62, 0x4c, 0x04, 0xf1, 0x92, 0x24, 0x98, 0x20, 0xbc, 0x24, diff --git a/examples/addsvc2/pkg/addendpoint/middleware.go b/examples/addsvc/pkg/addendpoint/middleware.go similarity index 100% rename from examples/addsvc2/pkg/addendpoint/middleware.go rename to examples/addsvc/pkg/addendpoint/middleware.go diff --git a/examples/addsvc2/pkg/addendpoint/set.go b/examples/addsvc/pkg/addendpoint/set.go similarity index 98% rename from examples/addsvc2/pkg/addendpoint/set.go rename to examples/addsvc/pkg/addendpoint/set.go index c8c1c6f42..3a65b083b 100644 --- a/examples/addsvc2/pkg/addendpoint/set.go +++ b/examples/addsvc/pkg/addendpoint/set.go @@ -14,7 +14,7 @@ import ( "github.com/go-kit/kit/ratelimit" "github.com/go-kit/kit/tracing/opentracing" - "github.com/go-kit/kit/examples/addsvc2/pkg/addservice" + "github.com/go-kit/kit/examples/addsvc/pkg/addservice" ) // Set collects all of the endpoints that compose an add service. It's meant to diff --git a/examples/addsvc2/pkg/addservice/middleware.go b/examples/addsvc/pkg/addservice/middleware.go similarity index 100% rename from examples/addsvc2/pkg/addservice/middleware.go rename to examples/addsvc/pkg/addservice/middleware.go diff --git a/examples/addsvc2/pkg/addservice/service.go b/examples/addsvc/pkg/addservice/service.go similarity index 100% rename from examples/addsvc2/pkg/addservice/service.go rename to examples/addsvc/pkg/addservice/service.go diff --git a/examples/addsvc2/pkg/addtransport/grpc.go b/examples/addsvc/pkg/addtransport/grpc.go similarity index 97% rename from examples/addsvc2/pkg/addtransport/grpc.go rename to examples/addsvc/pkg/addtransport/grpc.go index f8e4c2bba..82e9dd6e1 100644 --- a/examples/addsvc2/pkg/addtransport/grpc.go +++ b/examples/addsvc/pkg/addtransport/grpc.go @@ -19,9 +19,9 @@ import ( "github.com/go-kit/kit/tracing/opentracing" grpctransport "github.com/go-kit/kit/transport/grpc" - "github.com/go-kit/kit/examples/addsvc2/pb" - "github.com/go-kit/kit/examples/addsvc2/pkg/addendpoint" - "github.com/go-kit/kit/examples/addsvc2/pkg/addservice" + "github.com/go-kit/kit/examples/addsvc/pb" + "github.com/go-kit/kit/examples/addsvc/pkg/addendpoint" + "github.com/go-kit/kit/examples/addsvc/pkg/addservice" ) type grpcServer struct { diff --git a/examples/addsvc2/pkg/addtransport/http.go b/examples/addsvc/pkg/addtransport/http.go similarity index 98% rename from examples/addsvc2/pkg/addtransport/http.go rename to examples/addsvc/pkg/addtransport/http.go index 5ab8e679a..ad25e4f32 100644 --- a/examples/addsvc2/pkg/addtransport/http.go +++ b/examples/addsvc/pkg/addtransport/http.go @@ -22,8 +22,8 @@ import ( "github.com/go-kit/kit/tracing/opentracing" httptransport "github.com/go-kit/kit/transport/http" - "github.com/go-kit/kit/examples/addsvc2/pkg/addendpoint" - "github.com/go-kit/kit/examples/addsvc2/pkg/addservice" + "github.com/go-kit/kit/examples/addsvc/pkg/addendpoint" + "github.com/go-kit/kit/examples/addsvc/pkg/addservice" ) // NewHTTPHandler returns an HTTP handler that makes a set of endpoints diff --git a/examples/addsvc2/pkg/addtransport/thrift.go b/examples/addsvc/pkg/addtransport/thrift.go similarity index 85% rename from examples/addsvc2/pkg/addtransport/thrift.go rename to examples/addsvc/pkg/addtransport/thrift.go index ebbfc3687..4de44ba09 100644 --- a/examples/addsvc2/pkg/addtransport/thrift.go +++ b/examples/addsvc/pkg/addtransport/thrift.go @@ -11,9 +11,9 @@ import ( "github.com/go-kit/kit/endpoint" "github.com/go-kit/kit/ratelimit" - "github.com/go-kit/kit/examples/addsvc2/pkg/addendpoint" - "github.com/go-kit/kit/examples/addsvc2/pkg/addservice" - thriftadd "github.com/go-kit/kit/examples/addsvc2/thrift/gen-go/addsvc" + "github.com/go-kit/kit/examples/addsvc/pkg/addendpoint" + "github.com/go-kit/kit/examples/addsvc/pkg/addservice" + addthrift "github.com/go-kit/kit/examples/addsvc/thrift/gen-go/addsvc" ) type thriftServer struct { @@ -22,37 +22,37 @@ type thriftServer struct { } // NewThriftServer makes a set of endpoints available as a Thrift service. -func NewThriftServer(ctx context.Context, endpoints addendpoint.Set) thriftadd.AddService { +func NewThriftServer(ctx context.Context, endpoints addendpoint.Set) addthrift.AddService { return &thriftServer{ ctx: ctx, endpoints: endpoints, } } -func (s *thriftServer) Sum(a int64, b int64) (*thriftadd.SumReply, error) { +func (s *thriftServer) Sum(a int64, b int64) (*addthrift.SumReply, error) { request := addendpoint.SumRequest{A: int(a), B: int(b)} response, err := s.endpoints.SumEndpoint(s.ctx, request) if err != nil { return nil, err } resp := response.(addendpoint.SumResponse) - return &thriftadd.SumReply{Value: int64(resp.V), Err: err2str(resp.Err)}, nil + return &addthrift.SumReply{Value: int64(resp.V), Err: err2str(resp.Err)}, nil } -func (s *thriftServer) Concat(a string, b string) (*thriftadd.ConcatReply, error) { +func (s *thriftServer) Concat(a string, b string) (*addthrift.ConcatReply, error) { request := addendpoint.ConcatRequest{A: a, B: b} response, err := s.endpoints.ConcatEndpoint(s.ctx, request) if err != nil { return nil, err } resp := response.(addendpoint.ConcatResponse) - return &thriftadd.ConcatReply{Value: resp.V, Err: err2str(resp.Err)}, nil + return &addthrift.ConcatReply{Value: resp.V, Err: err2str(resp.Err)}, nil } // NewThriftClient returns an AddService backed by a Thrift server described by // the provided client. The caller is responsible for constructing the client, // and eventually closing the underlying transport. -func NewThriftClient(client *thriftadd.AddServiceClient) addservice.Service { +func NewThriftClient(client *addthrift.AddServiceClient) addservice.Service { // We construct a single ratelimiter middleware, to limit the total outgoing // QPS from this client to all methods on the remote instance. We also // construct per-endpoint circuitbreaker middlewares to demonstrate how @@ -96,7 +96,7 @@ func NewThriftClient(client *thriftadd.AddServiceClient) addservice.Service { // MakeThriftSumEndpoint returns an endpoint that invokes the passed Thrift client. // Useful only in clients, and only until a proper transport/thrift.Client exists. -func MakeThriftSumEndpoint(client *thriftadd.AddServiceClient) endpoint.Endpoint { +func MakeThriftSumEndpoint(client *addthrift.AddServiceClient) endpoint.Endpoint { return func(ctx context.Context, request interface{}) (interface{}, error) { req := request.(addendpoint.SumRequest) reply, err := client.Sum(int64(req.A), int64(req.B)) @@ -110,7 +110,7 @@ func MakeThriftSumEndpoint(client *thriftadd.AddServiceClient) endpoint.Endpoint // MakeThriftConcatEndpoint returns an endpoint that invokes the passed Thrift // client. Useful only in clients, and only until a proper // transport/thrift.Client exists. -func MakeThriftConcatEndpoint(client *thriftadd.AddServiceClient) endpoint.Endpoint { +func MakeThriftConcatEndpoint(client *addthrift.AddServiceClient) endpoint.Endpoint { return func(ctx context.Context, request interface{}) (interface{}, error) { req := request.(addendpoint.ConcatRequest) reply, err := client.Concat(req.A, req.B) diff --git a/examples/addsvc/service.go b/examples/addsvc/service.go deleted file mode 100644 index 971590cc0..000000000 --- a/examples/addsvc/service.go +++ /dev/null @@ -1,163 +0,0 @@ -package addsvc - -// This file contains the Service definition, and a basic service -// implementation. It also includes service middlewares. - -import ( - "context" - "errors" - "time" - - "github.com/go-kit/kit/log" - "github.com/go-kit/kit/metrics" -) - -// Service describes a service that adds things together. -type Service interface { - Sum(ctx context.Context, a, b int) (int, error) - Concat(ctx context.Context, a, b string) (string, error) -} - -// Business-domain errors like these may be served in two ways: returned -// directly by endpoints, or bundled into the response struct. Both methods can -// be made to work, but errors returned directly by endpoints are counted by -// middlewares that check errors, like circuit breakers. -// -// If you don't want that behavior -- and you probably don't -- then it's better -// to bundle errors into the response struct. - -var ( - // ErrTwoZeroes is an arbitrary business rule for the Add method. - ErrTwoZeroes = errors.New("can't sum two zeroes") - - // ErrIntOverflow protects the Add method. We've decided that this error - // indicates a misbehaving service and should count against e.g. circuit - // breakers. So, we return it directly in endpoints, to illustrate the - // difference. In a real service, this probably wouldn't be the case. - ErrIntOverflow = errors.New("integer overflow") - - // ErrMaxSizeExceeded protects the Concat method. - ErrMaxSizeExceeded = errors.New("result exceeds maximum size") -) - -// These annoying helper functions are required to translate Go error types to -// and from strings, which is the type we use in our IDLs to represent errors. -// There is special casing to treat empty strings as nil errors. - -func str2err(s string) error { - if s == "" { - return nil - } - return errors.New(s) -} - -func err2str(err error) string { - if err == nil { - return "" - } - return err.Error() -} - -// NewBasicService returns a naïve, stateless implementation of Service. -func NewBasicService() Service { - return basicService{} -} - -type basicService struct{} - -const ( - intMax = 1<<31 - 1 - intMin = -(intMax + 1) - maxLen = 102400 -) - -// Sum implements Service. -func (s basicService) Sum(_ context.Context, a, b int) (int, error) { - if a == 0 && b == 0 { - return 0, ErrTwoZeroes - } - if (b > 0 && a > (intMax-b)) || (b < 0 && a < (intMin-b)) { - return 0, ErrIntOverflow - } - return a + b, nil -} - -// Concat implements Service. -func (s basicService) Concat(_ context.Context, a, b string) (string, error) { - if len(a)+len(b) > maxLen { - return "", ErrMaxSizeExceeded - } - return a + b, nil -} - -// Middleware describes a service (as opposed to endpoint) middleware. -type Middleware func(Service) Service - -// ServiceLoggingMiddleware returns a service middleware that logs the -// parameters and result of each method invocation. -func ServiceLoggingMiddleware(logger log.Logger) Middleware { - return func(next Service) Service { - return serviceLoggingMiddleware{ - logger: logger, - next: next, - } - } -} - -type serviceLoggingMiddleware struct { - logger log.Logger - next Service -} - -func (mw serviceLoggingMiddleware) Sum(ctx context.Context, a, b int) (v int, err error) { - defer func(begin time.Time) { - mw.logger.Log( - "method", "Sum", - "a", a, "b", b, "result", v, "error", err, - "took", time.Since(begin), - ) - }(time.Now()) - return mw.next.Sum(ctx, a, b) -} - -func (mw serviceLoggingMiddleware) Concat(ctx context.Context, a, b string) (v string, err error) { - defer func(begin time.Time) { - mw.logger.Log( - "method", "Concat", - "a", a, "b", b, "result", v, "error", err, - "took", time.Since(begin), - ) - }(time.Now()) - return mw.next.Concat(ctx, a, b) -} - -// ServiceInstrumentingMiddleware returns a service middleware that instruments -// the number of integers summed and characters concatenated over the lifetime of -// the service. -func ServiceInstrumentingMiddleware(ints, chars metrics.Counter) Middleware { - return func(next Service) Service { - return serviceInstrumentingMiddleware{ - ints: ints, - chars: chars, - next: next, - } - } -} - -type serviceInstrumentingMiddleware struct { - ints metrics.Counter - chars metrics.Counter - next Service -} - -func (mw serviceInstrumentingMiddleware) Sum(ctx context.Context, a, b int) (int, error) { - v, err := mw.next.Sum(ctx, a, b) - mw.ints.Add(float64(v)) - return v, err -} - -func (mw serviceInstrumentingMiddleware) Concat(ctx context.Context, a, b string) (string, error) { - v, err := mw.next.Concat(ctx, a, b) - mw.chars.Add(float64(len(v))) - return v, err -} diff --git a/examples/addsvc/transport_grpc.go b/examples/addsvc/transport_grpc.go deleted file mode 100644 index dcfc03a05..000000000 --- a/examples/addsvc/transport_grpc.go +++ /dev/null @@ -1,118 +0,0 @@ -package addsvc - -// This file provides server-side bindings for the gRPC transport. -// It utilizes the transport/grpc.Server. - -import ( - "context" - - stdopentracing "github.com/opentracing/opentracing-go" - oldcontext "golang.org/x/net/context" - - "github.com/go-kit/kit/examples/addsvc/pb" - "github.com/go-kit/kit/log" - "github.com/go-kit/kit/tracing/opentracing" - grpctransport "github.com/go-kit/kit/transport/grpc" -) - -// MakeGRPCServer makes a set of endpoints available as a gRPC AddServer. -func MakeGRPCServer(endpoints Endpoints, tracer stdopentracing.Tracer, logger log.Logger) pb.AddServer { - options := []grpctransport.ServerOption{ - grpctransport.ServerErrorLogger(logger), - } - return &grpcServer{ - sum: grpctransport.NewServer( - endpoints.SumEndpoint, - DecodeGRPCSumRequest, - EncodeGRPCSumResponse, - append(options, grpctransport.ServerBefore(opentracing.FromGRPCRequest(tracer, "Sum", logger)))..., - ), - concat: grpctransport.NewServer( - endpoints.ConcatEndpoint, - DecodeGRPCConcatRequest, - EncodeGRPCConcatResponse, - append(options, grpctransport.ServerBefore(opentracing.FromGRPCRequest(tracer, "Concat", logger)))..., - ), - } -} - -type grpcServer struct { - sum grpctransport.Handler - concat grpctransport.Handler -} - -func (s *grpcServer) Sum(ctx oldcontext.Context, req *pb.SumRequest) (*pb.SumReply, error) { - _, rep, err := s.sum.ServeGRPC(ctx, req) - if err != nil { - return nil, err - } - return rep.(*pb.SumReply), nil -} - -func (s *grpcServer) Concat(ctx oldcontext.Context, req *pb.ConcatRequest) (*pb.ConcatReply, error) { - _, rep, err := s.concat.ServeGRPC(ctx, req) - if err != nil { - return nil, err - } - return rep.(*pb.ConcatReply), nil -} - -// DecodeGRPCSumRequest is a transport/grpc.DecodeRequestFunc that converts a -// gRPC sum request to a user-domain sum request. Primarily useful in a server. -func DecodeGRPCSumRequest(_ context.Context, grpcReq interface{}) (interface{}, error) { - req := grpcReq.(*pb.SumRequest) - return sumRequest{A: int(req.A), B: int(req.B)}, nil -} - -// DecodeGRPCConcatRequest is a transport/grpc.DecodeRequestFunc that converts a -// gRPC concat request to a user-domain concat request. Primarily useful in a -// server. -func DecodeGRPCConcatRequest(_ context.Context, grpcReq interface{}) (interface{}, error) { - req := grpcReq.(*pb.ConcatRequest) - return concatRequest{A: req.A, B: req.B}, nil -} - -// DecodeGRPCSumResponse is a transport/grpc.DecodeResponseFunc that converts a -// gRPC sum reply to a user-domain sum response. Primarily useful in a client. -func DecodeGRPCSumResponse(_ context.Context, grpcReply interface{}) (interface{}, error) { - reply := grpcReply.(*pb.SumReply) - return sumResponse{V: int(reply.V), Err: str2err(reply.Err)}, nil -} - -// DecodeGRPCConcatResponse is a transport/grpc.DecodeResponseFunc that converts -// a gRPC concat reply to a user-domain concat response. Primarily useful in a -// client. -func DecodeGRPCConcatResponse(_ context.Context, grpcReply interface{}) (interface{}, error) { - reply := grpcReply.(*pb.ConcatReply) - return concatResponse{V: reply.V, Err: str2err(reply.Err)}, nil -} - -// EncodeGRPCSumResponse is a transport/grpc.EncodeResponseFunc that converts a -// user-domain sum response to a gRPC sum reply. Primarily useful in a server. -func EncodeGRPCSumResponse(_ context.Context, response interface{}) (interface{}, error) { - resp := response.(sumResponse) - return &pb.SumReply{V: int64(resp.V), Err: err2str(resp.Err)}, nil -} - -// EncodeGRPCConcatResponse is a transport/grpc.EncodeResponseFunc that converts -// a user-domain concat response to a gRPC concat reply. Primarily useful in a -// server. -func EncodeGRPCConcatResponse(_ context.Context, response interface{}) (interface{}, error) { - resp := response.(concatResponse) - return &pb.ConcatReply{V: resp.V, Err: err2str(resp.Err)}, nil -} - -// EncodeGRPCSumRequest is a transport/grpc.EncodeRequestFunc that converts a -// user-domain sum request to a gRPC sum request. Primarily useful in a client. -func EncodeGRPCSumRequest(_ context.Context, request interface{}) (interface{}, error) { - req := request.(sumRequest) - return &pb.SumRequest{A: int64(req.A), B: int64(req.B)}, nil -} - -// EncodeGRPCConcatRequest is a transport/grpc.EncodeRequestFunc that converts a -// user-domain concat request to a gRPC concat request. Primarily useful in a -// client. -func EncodeGRPCConcatRequest(_ context.Context, request interface{}) (interface{}, error) { - req := request.(concatRequest) - return &pb.ConcatRequest{A: req.A, B: req.B}, nil -} diff --git a/examples/addsvc/transport_http.go b/examples/addsvc/transport_http.go deleted file mode 100644 index 75a9b839b..000000000 --- a/examples/addsvc/transport_http.go +++ /dev/null @@ -1,130 +0,0 @@ -package addsvc - -// This file provides server-side bindings for the HTTP transport. -// It utilizes the transport/http.Server. - -import ( - "bytes" - "context" - "encoding/json" - "errors" - "io/ioutil" - "net/http" - - stdopentracing "github.com/opentracing/opentracing-go" - - "github.com/go-kit/kit/log" - "github.com/go-kit/kit/tracing/opentracing" - httptransport "github.com/go-kit/kit/transport/http" -) - -// MakeHTTPHandler returns a handler that makes a set of endpoints available -// on predefined paths. -func MakeHTTPHandler(endpoints Endpoints, tracer stdopentracing.Tracer, logger log.Logger) http.Handler { - options := []httptransport.ServerOption{ - httptransport.ServerErrorEncoder(errorEncoder), - httptransport.ServerErrorLogger(logger), - } - m := http.NewServeMux() - m.Handle("/sum", httptransport.NewServer( - endpoints.SumEndpoint, - DecodeHTTPSumRequest, - EncodeHTTPGenericResponse, - append(options, httptransport.ServerBefore(opentracing.FromHTTPRequest(tracer, "Sum", logger)))..., - )) - m.Handle("/concat", httptransport.NewServer( - endpoints.ConcatEndpoint, - DecodeHTTPConcatRequest, - EncodeHTTPGenericResponse, - append(options, httptransport.ServerBefore(opentracing.FromHTTPRequest(tracer, "Concat", logger)))..., - )) - return m -} - -func errorEncoder(_ context.Context, err error, w http.ResponseWriter) { - code := http.StatusInternalServerError - msg := err.Error() - - switch err { - case ErrTwoZeroes, ErrMaxSizeExceeded, ErrIntOverflow: - code = http.StatusBadRequest - } - - w.WriteHeader(code) - json.NewEncoder(w).Encode(errorWrapper{Error: msg}) -} - -func errorDecoder(r *http.Response) error { - var w errorWrapper - if err := json.NewDecoder(r.Body).Decode(&w); err != nil { - return err - } - return errors.New(w.Error) -} - -type errorWrapper struct { - Error string `json:"error"` -} - -// DecodeHTTPSumRequest is a transport/http.DecodeRequestFunc that decodes a -// JSON-encoded sum request from the HTTP request body. Primarily useful in a -// server. -func DecodeHTTPSumRequest(_ context.Context, r *http.Request) (interface{}, error) { - var req sumRequest - err := json.NewDecoder(r.Body).Decode(&req) - return req, err -} - -// DecodeHTTPConcatRequest is a transport/http.DecodeRequestFunc that decodes a -// JSON-encoded concat request from the HTTP request body. Primarily useful in a -// server. -func DecodeHTTPConcatRequest(_ context.Context, r *http.Request) (interface{}, error) { - var req concatRequest - err := json.NewDecoder(r.Body).Decode(&req) - return req, err -} - -// DecodeHTTPSumResponse is a transport/http.DecodeResponseFunc that decodes a -// JSON-encoded sum response from the HTTP response body. If the response has a -// non-200 status code, we will interpret that as an error and attempt to decode -// the specific error message from the response body. Primarily useful in a -// client. -func DecodeHTTPSumResponse(_ context.Context, r *http.Response) (interface{}, error) { - if r.StatusCode != http.StatusOK { - return nil, errorDecoder(r) - } - var resp sumResponse - err := json.NewDecoder(r.Body).Decode(&resp) - return resp, err -} - -// DecodeHTTPConcatResponse is a transport/http.DecodeResponseFunc that decodes -// a JSON-encoded concat response from the HTTP response body. If the response -// has a non-200 status code, we will interpret that as an error and attempt to -// decode the specific error message from the response body. Primarily useful in -// a client. -func DecodeHTTPConcatResponse(_ context.Context, r *http.Response) (interface{}, error) { - if r.StatusCode != http.StatusOK { - return nil, errorDecoder(r) - } - var resp concatResponse - err := json.NewDecoder(r.Body).Decode(&resp) - return resp, err -} - -// EncodeHTTPGenericRequest is a transport/http.EncodeRequestFunc that -// JSON-encodes any request to the request body. Primarily useful in a client. -func EncodeHTTPGenericRequest(_ context.Context, r *http.Request, request interface{}) error { - var buf bytes.Buffer - if err := json.NewEncoder(&buf).Encode(request); err != nil { - return err - } - r.Body = ioutil.NopCloser(&buf) - return nil -} - -// EncodeHTTPGenericResponse is a transport/http.EncodeResponseFunc that encodes -// the response as JSON to the response writer. Primarily useful in a server. -func EncodeHTTPGenericResponse(_ context.Context, w http.ResponseWriter, response interface{}) error { - return json.NewEncoder(w).Encode(response) -} diff --git a/examples/addsvc/transport_thrift.go b/examples/addsvc/transport_thrift.go deleted file mode 100644 index 593cd31e5..000000000 --- a/examples/addsvc/transport_thrift.go +++ /dev/null @@ -1,73 +0,0 @@ -package addsvc - -// This file provides server-side bindings for the Thrift transport. -// -// This file also provides endpoint constructors that utilize a Thrift client, -// for use in client packages, because package transport/thrift doesn't exist -// yet. See https://github.com/go-kit/kit/issues/184. - -import ( - "context" - - "github.com/go-kit/kit/endpoint" - thriftadd "github.com/go-kit/kit/examples/addsvc/thrift/gen-go/addsvc" -) - -// MakeThriftHandler makes a set of endpoints available as a Thrift service. -func MakeThriftHandler(ctx context.Context, e Endpoints) thriftadd.AddService { - return &thriftServer{ - ctx: ctx, - sum: e.SumEndpoint, - concat: e.ConcatEndpoint, - } -} - -type thriftServer struct { - ctx context.Context - sum endpoint.Endpoint - concat endpoint.Endpoint -} - -func (s *thriftServer) Sum(a int64, b int64) (*thriftadd.SumReply, error) { - request := sumRequest{A: int(a), B: int(b)} - response, err := s.sum(s.ctx, request) - if err != nil { - return nil, err - } - resp := response.(sumResponse) - return &thriftadd.SumReply{Value: int64(resp.V), Err: err2str(resp.Err)}, nil -} - -func (s *thriftServer) Concat(a string, b string) (*thriftadd.ConcatReply, error) { - request := concatRequest{A: a, B: b} - response, err := s.concat(s.ctx, request) - if err != nil { - return nil, err - } - resp := response.(concatResponse) - return &thriftadd.ConcatReply{Value: resp.V, Err: err2str(resp.Err)}, nil -} - -// MakeThriftSumEndpoint returns an endpoint that invokes the passed Thrift client. -// Useful only in clients, and only until a proper transport/thrift.Client exists. -func MakeThriftSumEndpoint(client *thriftadd.AddServiceClient) endpoint.Endpoint { - return func(ctx context.Context, request interface{}) (interface{}, error) { - req := request.(sumRequest) - reply, err := client.Sum(int64(req.A), int64(req.B)) - if err == ErrIntOverflow { - return nil, err // special case; see comment on ErrIntOverflow - } - return sumResponse{V: int(reply.Value), Err: err}, nil - } -} - -// MakeThriftConcatEndpoint returns an endpoint that invokes the passed Thrift -// client. Useful only in clients, and only until a proper -// transport/thrift.Client exists. -func MakeThriftConcatEndpoint(client *thriftadd.AddServiceClient) endpoint.Endpoint { - return func(ctx context.Context, request interface{}) (interface{}, error) { - req := request.(concatRequest) - reply, err := client.Concat(req.A, req.B) - return concatResponse{V: reply.Value, Err: err}, nil - } -} diff --git a/examples/addsvc2/pb/addsvc.pb.go b/examples/addsvc2/pb/addsvc.pb.go deleted file mode 100644 index 781b50b75..000000000 --- a/examples/addsvc2/pb/addsvc.pb.go +++ /dev/null @@ -1,270 +0,0 @@ -// Code generated by protoc-gen-go. DO NOT EDIT. -// source: addsvc.proto - -/* -Package pb is a generated protocol buffer package. - -It is generated from these files: - addsvc.proto - -It has these top-level messages: - SumRequest - SumReply - ConcatRequest - ConcatReply -*/ -package pb - -import proto "github.com/golang/protobuf/proto" -import fmt "fmt" -import math "math" - -import ( - context "golang.org/x/net/context" - grpc "google.golang.org/grpc" -) - -// Reference imports to suppress errors if they are not otherwise used. -var _ = proto.Marshal -var _ = fmt.Errorf -var _ = math.Inf - -// This is a compile-time assertion to ensure that this generated file -// is compatible with the proto package it is being compiled against. -// A compilation error at this line likely means your copy of the -// proto package needs to be updated. -const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package - -// The sum request contains two parameters. -type SumRequest struct { - A int64 `protobuf:"varint,1,opt,name=a" json:"a,omitempty"` - B int64 `protobuf:"varint,2,opt,name=b" json:"b,omitempty"` -} - -func (m *SumRequest) Reset() { *m = SumRequest{} } -func (m *SumRequest) String() string { return proto.CompactTextString(m) } -func (*SumRequest) ProtoMessage() {} -func (*SumRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} } - -func (m *SumRequest) GetA() int64 { - if m != nil { - return m.A - } - return 0 -} - -func (m *SumRequest) GetB() int64 { - if m != nil { - return m.B - } - return 0 -} - -// The sum response contains the result of the calculation. -type SumReply struct { - V int64 `protobuf:"varint,1,opt,name=v" json:"v,omitempty"` - Err string `protobuf:"bytes,2,opt,name=err" json:"err,omitempty"` -} - -func (m *SumReply) Reset() { *m = SumReply{} } -func (m *SumReply) String() string { return proto.CompactTextString(m) } -func (*SumReply) ProtoMessage() {} -func (*SumReply) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} } - -func (m *SumReply) GetV() int64 { - if m != nil { - return m.V - } - return 0 -} - -func (m *SumReply) GetErr() string { - if m != nil { - return m.Err - } - return "" -} - -// The Concat request contains two parameters. -type ConcatRequest struct { - A string `protobuf:"bytes,1,opt,name=a" json:"a,omitempty"` - B string `protobuf:"bytes,2,opt,name=b" json:"b,omitempty"` -} - -func (m *ConcatRequest) Reset() { *m = ConcatRequest{} } -func (m *ConcatRequest) String() string { return proto.CompactTextString(m) } -func (*ConcatRequest) ProtoMessage() {} -func (*ConcatRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2} } - -func (m *ConcatRequest) GetA() string { - if m != nil { - return m.A - } - return "" -} - -func (m *ConcatRequest) GetB() string { - if m != nil { - return m.B - } - return "" -} - -// The Concat response contains the result of the concatenation. -type ConcatReply struct { - V string `protobuf:"bytes,1,opt,name=v" json:"v,omitempty"` - Err string `protobuf:"bytes,2,opt,name=err" json:"err,omitempty"` -} - -func (m *ConcatReply) Reset() { *m = ConcatReply{} } -func (m *ConcatReply) String() string { return proto.CompactTextString(m) } -func (*ConcatReply) ProtoMessage() {} -func (*ConcatReply) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{3} } - -func (m *ConcatReply) GetV() string { - if m != nil { - return m.V - } - return "" -} - -func (m *ConcatReply) GetErr() string { - if m != nil { - return m.Err - } - return "" -} - -func init() { - proto.RegisterType((*SumRequest)(nil), "pb.SumRequest") - proto.RegisterType((*SumReply)(nil), "pb.SumReply") - proto.RegisterType((*ConcatRequest)(nil), "pb.ConcatRequest") - proto.RegisterType((*ConcatReply)(nil), "pb.ConcatReply") -} - -// Reference imports to suppress errors if they are not otherwise used. -var _ context.Context -var _ grpc.ClientConn - -// This is a compile-time assertion to ensure that this generated file -// is compatible with the grpc package it is being compiled against. -const _ = grpc.SupportPackageIsVersion4 - -// Client API for Add service - -type AddClient interface { - // Sums two integers. - Sum(ctx context.Context, in *SumRequest, opts ...grpc.CallOption) (*SumReply, error) - // Concatenates two strings - Concat(ctx context.Context, in *ConcatRequest, opts ...grpc.CallOption) (*ConcatReply, error) -} - -type addClient struct { - cc *grpc.ClientConn -} - -func NewAddClient(cc *grpc.ClientConn) AddClient { - return &addClient{cc} -} - -func (c *addClient) Sum(ctx context.Context, in *SumRequest, opts ...grpc.CallOption) (*SumReply, error) { - out := new(SumReply) - err := grpc.Invoke(ctx, "/pb.Add/Sum", in, out, c.cc, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *addClient) Concat(ctx context.Context, in *ConcatRequest, opts ...grpc.CallOption) (*ConcatReply, error) { - out := new(ConcatReply) - err := grpc.Invoke(ctx, "/pb.Add/Concat", in, out, c.cc, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -// Server API for Add service - -type AddServer interface { - // Sums two integers. - Sum(context.Context, *SumRequest) (*SumReply, error) - // Concatenates two strings - Concat(context.Context, *ConcatRequest) (*ConcatReply, error) -} - -func RegisterAddServer(s *grpc.Server, srv AddServer) { - s.RegisterService(&_Add_serviceDesc, srv) -} - -func _Add_Sum_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(SumRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(AddServer).Sum(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/pb.Add/Sum", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(AddServer).Sum(ctx, req.(*SumRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _Add_Concat_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(ConcatRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(AddServer).Concat(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/pb.Add/Concat", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(AddServer).Concat(ctx, req.(*ConcatRequest)) - } - return interceptor(ctx, in, info, handler) -} - -var _Add_serviceDesc = grpc.ServiceDesc{ - ServiceName: "pb.Add", - HandlerType: (*AddServer)(nil), - Methods: []grpc.MethodDesc{ - { - MethodName: "Sum", - Handler: _Add_Sum_Handler, - }, - { - MethodName: "Concat", - Handler: _Add_Concat_Handler, - }, - }, - Streams: []grpc.StreamDesc{}, - Metadata: "addsvc.proto", -} - -func init() { proto.RegisterFile("addsvc.proto", fileDescriptor0) } - -var fileDescriptor0 = []byte{ - // 189 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xe2, 0x49, 0x4c, 0x49, 0x29, - 0x2e, 0x4b, 0xd6, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x62, 0x2a, 0x48, 0x52, 0xd2, 0xe0, 0xe2, - 0x0a, 0x2e, 0xcd, 0x0d, 0x4a, 0x2d, 0x2c, 0x4d, 0x2d, 0x2e, 0x11, 0xe2, 0xe1, 0x62, 0x4c, 0x94, - 0x60, 0x54, 0x60, 0xd4, 0x60, 0x0e, 0x62, 0x4c, 0x04, 0xf1, 0x92, 0x24, 0x98, 0x20, 0xbc, 0x24, - 0x25, 0x2d, 0x2e, 0x0e, 0xb0, 0xca, 0x82, 0x9c, 0x4a, 0x90, 0x4c, 0x19, 0x4c, 0x5d, 0x99, 0x90, - 0x00, 0x17, 0x73, 0x6a, 0x51, 0x11, 0x58, 0x25, 0x67, 0x10, 0x88, 0xa9, 0xa4, 0xcd, 0xc5, 0xeb, - 0x9c, 0x9f, 0x97, 0x9c, 0x58, 0x82, 0x61, 0x30, 0x27, 0x8a, 0xc1, 0x9c, 0x20, 0x83, 0x75, 0xb9, - 0xb8, 0x61, 0x8a, 0x51, 0xcc, 0xe6, 0xc4, 0x6a, 0xb6, 0x51, 0x0c, 0x17, 0xb3, 0x63, 0x4a, 0x8a, - 0x90, 0x2a, 0x17, 0x73, 0x70, 0x69, 0xae, 0x10, 0x9f, 0x5e, 0x41, 0x92, 0x1e, 0xc2, 0x07, 0x52, - 0x3c, 0x70, 0x7e, 0x41, 0x4e, 0xa5, 0x12, 0x83, 0x90, 0x1e, 0x17, 0x1b, 0xc4, 0x70, 0x21, 0x41, - 0x90, 0x0c, 0x8a, 0xab, 0xa4, 0xf8, 0x91, 0x85, 0xc0, 0xea, 0x93, 0xd8, 0xc0, 0x41, 0x63, 0x0c, - 0x08, 0x00, 0x00, 0xff, 0xff, 0xdc, 0x37, 0x81, 0x99, 0x2a, 0x01, 0x00, 0x00, -} diff --git a/examples/addsvc2/pb/addsvc.proto b/examples/addsvc2/pb/addsvc.proto deleted file mode 100644 index cf61532f3..000000000 --- a/examples/addsvc2/pb/addsvc.proto +++ /dev/null @@ -1,36 +0,0 @@ -syntax = "proto3"; - -package pb; - -// The Add service definition. -service Add { - // Sums two integers. - rpc Sum (SumRequest) returns (SumReply) {} - - // Concatenates two strings - rpc Concat (ConcatRequest) returns (ConcatReply) {} -} - -// The sum request contains two parameters. -message SumRequest { - int64 a = 1; - int64 b = 2; -} - -// The sum response contains the result of the calculation. -message SumReply { - int64 v = 1; - string err = 2; -} - -// The Concat request contains two parameters. -message ConcatRequest { - string a = 1; - string b = 2; -} - -// The Concat response contains the result of the concatenation. -message ConcatReply { - string v = 1; - string err = 2; -} diff --git a/examples/addsvc2/pb/compile.sh b/examples/addsvc2/pb/compile.sh deleted file mode 100755 index c0268442a..000000000 --- a/examples/addsvc2/pb/compile.sh +++ /dev/null @@ -1,14 +0,0 @@ -#!/usr/bin/env sh - -# Install proto3 from source -# brew install autoconf automake libtool -# git clone https://github.com/google/protobuf -# ./autogen.sh ; ./configure ; make ; make install -# -# Update protoc Go bindings via -# go get -u github.com/golang/protobuf/{proto,protoc-gen-go} -# -# See also -# https://github.com/grpc/grpc-go/tree/master/examples - -protoc addsvc.proto --go_out=plugins=grpc:. diff --git a/examples/addsvc2/thrift/addsvc.thrift b/examples/addsvc2/thrift/addsvc.thrift deleted file mode 100644 index e67ce1b21..000000000 --- a/examples/addsvc2/thrift/addsvc.thrift +++ /dev/null @@ -1,14 +0,0 @@ -struct SumReply { - 1: i64 value - 2: string err -} - -struct ConcatReply { - 1: string value - 2: string err -} - -service AddService { - SumReply Sum(1: i64 a, 2: i64 b) - ConcatReply Concat(1: string a, 2: string b) -} diff --git a/examples/addsvc2/thrift/compile.sh b/examples/addsvc2/thrift/compile.sh deleted file mode 100755 index add8ffa25..000000000 --- a/examples/addsvc2/thrift/compile.sh +++ /dev/null @@ -1,5 +0,0 @@ -#!/usr/bin/env sh - -# See also https://thrift.apache.org/tutorial/go - -thrift -r --gen "go:package_prefix=github.com/go-kit/kit/examples/addsvc2/thrift/gen-go/,thrift_import=github.com/apache/thrift/lib/go/thrift" addsvc.thrift diff --git a/examples/addsvc2/thrift/gen-go/addsvc/add_service-remote/add_service-remote.go b/examples/addsvc2/thrift/gen-go/addsvc/add_service-remote/add_service-remote.go deleted file mode 100755 index b8ce67ca2..000000000 --- a/examples/addsvc2/thrift/gen-go/addsvc/add_service-remote/add_service-remote.go +++ /dev/null @@ -1,157 +0,0 @@ -// Autogenerated by Thrift Compiler (0.9.3) -// DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING - -package main - -import ( - "flag" - "fmt" - "github.com/apache/thrift/lib/go/thrift" - "github.com/go-kit/kit/examples/addsvc/thrift/gen-go/addsvc" - "math" - "net" - "net/url" - "os" - "strconv" - "strings" -) - -func Usage() { - fmt.Fprintln(os.Stderr, "Usage of ", os.Args[0], " [-h host:port] [-u url] [-f[ramed]] function [arg1 [arg2...]]:") - flag.PrintDefaults() - fmt.Fprintln(os.Stderr, "\nFunctions:") - fmt.Fprintln(os.Stderr, " SumReply Sum(i64 a, i64 b)") - fmt.Fprintln(os.Stderr, " ConcatReply Concat(string a, string b)") - fmt.Fprintln(os.Stderr) - os.Exit(0) -} - -func main() { - flag.Usage = Usage - var host string - var port int - var protocol string - var urlString string - var framed bool - var useHttp bool - var parsedUrl url.URL - var trans thrift.TTransport - _ = strconv.Atoi - _ = math.Abs - flag.Usage = Usage - flag.StringVar(&host, "h", "localhost", "Specify host and port") - flag.IntVar(&port, "p", 9090, "Specify port") - flag.StringVar(&protocol, "P", "binary", "Specify the protocol (binary, compact, simplejson, json)") - flag.StringVar(&urlString, "u", "", "Specify the url") - flag.BoolVar(&framed, "framed", false, "Use framed transport") - flag.BoolVar(&useHttp, "http", false, "Use http") - flag.Parse() - - if len(urlString) > 0 { - parsedUrl, err := url.Parse(urlString) - if err != nil { - fmt.Fprintln(os.Stderr, "Error parsing URL: ", err) - flag.Usage() - } - host = parsedUrl.Host - useHttp = len(parsedUrl.Scheme) <= 0 || parsedUrl.Scheme == "http" - } else if useHttp { - _, err := url.Parse(fmt.Sprint("http://", host, ":", port)) - if err != nil { - fmt.Fprintln(os.Stderr, "Error parsing URL: ", err) - flag.Usage() - } - } - - cmd := flag.Arg(0) - var err error - if useHttp { - trans, err = thrift.NewTHttpClient(parsedUrl.String()) - } else { - portStr := fmt.Sprint(port) - if strings.Contains(host, ":") { - host, portStr, err = net.SplitHostPort(host) - if err != nil { - fmt.Fprintln(os.Stderr, "error with host:", err) - os.Exit(1) - } - } - trans, err = thrift.NewTSocket(net.JoinHostPort(host, portStr)) - if err != nil { - fmt.Fprintln(os.Stderr, "error resolving address:", err) - os.Exit(1) - } - if framed { - trans = thrift.NewTFramedTransport(trans) - } - } - if err != nil { - fmt.Fprintln(os.Stderr, "Error creating transport", err) - os.Exit(1) - } - defer trans.Close() - var protocolFactory thrift.TProtocolFactory - switch protocol { - case "compact": - protocolFactory = thrift.NewTCompactProtocolFactory() - break - case "simplejson": - protocolFactory = thrift.NewTSimpleJSONProtocolFactory() - break - case "json": - protocolFactory = thrift.NewTJSONProtocolFactory() - break - case "binary", "": - protocolFactory = thrift.NewTBinaryProtocolFactoryDefault() - break - default: - fmt.Fprintln(os.Stderr, "Invalid protocol specified: ", protocol) - Usage() - os.Exit(1) - } - client := addsvc.NewAddServiceClientFactory(trans, protocolFactory) - if err := trans.Open(); err != nil { - fmt.Fprintln(os.Stderr, "Error opening socket to ", host, ":", port, " ", err) - os.Exit(1) - } - - switch cmd { - case "Sum": - if flag.NArg()-1 != 2 { - fmt.Fprintln(os.Stderr, "Sum requires 2 args") - flag.Usage() - } - argvalue0, err6 := (strconv.ParseInt(flag.Arg(1), 10, 64)) - if err6 != nil { - Usage() - return - } - value0 := argvalue0 - argvalue1, err7 := (strconv.ParseInt(flag.Arg(2), 10, 64)) - if err7 != nil { - Usage() - return - } - value1 := argvalue1 - fmt.Print(client.Sum(value0, value1)) - fmt.Print("\n") - break - case "Concat": - if flag.NArg()-1 != 2 { - fmt.Fprintln(os.Stderr, "Concat requires 2 args") - flag.Usage() - } - argvalue0 := flag.Arg(1) - value0 := argvalue0 - argvalue1 := flag.Arg(2) - value1 := argvalue1 - fmt.Print(client.Concat(value0, value1)) - fmt.Print("\n") - break - case "": - Usage() - break - default: - fmt.Fprintln(os.Stderr, "Invalid function ", cmd) - } -} diff --git a/examples/addsvc2/thrift/gen-go/addsvc/addservice.go b/examples/addsvc2/thrift/gen-go/addsvc/addservice.go deleted file mode 100644 index 3f3aeebf1..000000000 --- a/examples/addsvc2/thrift/gen-go/addsvc/addservice.go +++ /dev/null @@ -1,807 +0,0 @@ -// Autogenerated by Thrift Compiler (0.9.3) -// DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING - -package addsvc - -import ( - "bytes" - "fmt" - "github.com/apache/thrift/lib/go/thrift" -) - -// (needed to ensure safety because of naive import list construction.) -var _ = thrift.ZERO -var _ = fmt.Printf -var _ = bytes.Equal - -type AddService interface { - // Parameters: - // - A - // - B - Sum(a int64, b int64) (r *SumReply, err error) - // Parameters: - // - A - // - B - Concat(a string, b string) (r *ConcatReply, err error) -} - -type AddServiceClient struct { - Transport thrift.TTransport - ProtocolFactory thrift.TProtocolFactory - InputProtocol thrift.TProtocol - OutputProtocol thrift.TProtocol - SeqId int32 -} - -func NewAddServiceClientFactory(t thrift.TTransport, f thrift.TProtocolFactory) *AddServiceClient { - return &AddServiceClient{Transport: t, - ProtocolFactory: f, - InputProtocol: f.GetProtocol(t), - OutputProtocol: f.GetProtocol(t), - SeqId: 0, - } -} - -func NewAddServiceClientProtocol(t thrift.TTransport, iprot thrift.TProtocol, oprot thrift.TProtocol) *AddServiceClient { - return &AddServiceClient{Transport: t, - ProtocolFactory: nil, - InputProtocol: iprot, - OutputProtocol: oprot, - SeqId: 0, - } -} - -// Parameters: -// - A -// - B -func (p *AddServiceClient) Sum(a int64, b int64) (r *SumReply, err error) { - if err = p.sendSum(a, b); err != nil { - return - } - return p.recvSum() -} - -func (p *AddServiceClient) sendSum(a int64, b int64) (err error) { - oprot := p.OutputProtocol - if oprot == nil { - oprot = p.ProtocolFactory.GetProtocol(p.Transport) - p.OutputProtocol = oprot - } - p.SeqId++ - if err = oprot.WriteMessageBegin("Sum", thrift.CALL, p.SeqId); err != nil { - return - } - args := AddServiceSumArgs{ - A: a, - B: b, - } - if err = args.Write(oprot); err != nil { - return - } - if err = oprot.WriteMessageEnd(); err != nil { - return - } - return oprot.Flush() -} - -func (p *AddServiceClient) recvSum() (value *SumReply, err error) { - iprot := p.InputProtocol - if iprot == nil { - iprot = p.ProtocolFactory.GetProtocol(p.Transport) - p.InputProtocol = iprot - } - method, mTypeId, seqId, err := iprot.ReadMessageBegin() - if err != nil { - return - } - if method != "Sum" { - err = thrift.NewTApplicationException(thrift.WRONG_METHOD_NAME, "Sum failed: wrong method name") - return - } - if p.SeqId != seqId { - err = thrift.NewTApplicationException(thrift.BAD_SEQUENCE_ID, "Sum failed: out of sequence response") - return - } - if mTypeId == thrift.EXCEPTION { - error0 := thrift.NewTApplicationException(thrift.UNKNOWN_APPLICATION_EXCEPTION, "Unknown Exception") - var error1 error - error1, err = error0.Read(iprot) - if err != nil { - return - } - if err = iprot.ReadMessageEnd(); err != nil { - return - } - err = error1 - return - } - if mTypeId != thrift.REPLY { - err = thrift.NewTApplicationException(thrift.INVALID_MESSAGE_TYPE_EXCEPTION, "Sum failed: invalid message type") - return - } - result := AddServiceSumResult{} - if err = result.Read(iprot); err != nil { - return - } - if err = iprot.ReadMessageEnd(); err != nil { - return - } - value = result.GetSuccess() - return -} - -// Parameters: -// - A -// - B -func (p *AddServiceClient) Concat(a string, b string) (r *ConcatReply, err error) { - if err = p.sendConcat(a, b); err != nil { - return - } - return p.recvConcat() -} - -func (p *AddServiceClient) sendConcat(a string, b string) (err error) { - oprot := p.OutputProtocol - if oprot == nil { - oprot = p.ProtocolFactory.GetProtocol(p.Transport) - p.OutputProtocol = oprot - } - p.SeqId++ - if err = oprot.WriteMessageBegin("Concat", thrift.CALL, p.SeqId); err != nil { - return - } - args := AddServiceConcatArgs{ - A: a, - B: b, - } - if err = args.Write(oprot); err != nil { - return - } - if err = oprot.WriteMessageEnd(); err != nil { - return - } - return oprot.Flush() -} - -func (p *AddServiceClient) recvConcat() (value *ConcatReply, err error) { - iprot := p.InputProtocol - if iprot == nil { - iprot = p.ProtocolFactory.GetProtocol(p.Transport) - p.InputProtocol = iprot - } - method, mTypeId, seqId, err := iprot.ReadMessageBegin() - if err != nil { - return - } - if method != "Concat" { - err = thrift.NewTApplicationException(thrift.WRONG_METHOD_NAME, "Concat failed: wrong method name") - return - } - if p.SeqId != seqId { - err = thrift.NewTApplicationException(thrift.BAD_SEQUENCE_ID, "Concat failed: out of sequence response") - return - } - if mTypeId == thrift.EXCEPTION { - error2 := thrift.NewTApplicationException(thrift.UNKNOWN_APPLICATION_EXCEPTION, "Unknown Exception") - var error3 error - error3, err = error2.Read(iprot) - if err != nil { - return - } - if err = iprot.ReadMessageEnd(); err != nil { - return - } - err = error3 - return - } - if mTypeId != thrift.REPLY { - err = thrift.NewTApplicationException(thrift.INVALID_MESSAGE_TYPE_EXCEPTION, "Concat failed: invalid message type") - return - } - result := AddServiceConcatResult{} - if err = result.Read(iprot); err != nil { - return - } - if err = iprot.ReadMessageEnd(); err != nil { - return - } - value = result.GetSuccess() - return -} - -type AddServiceProcessor struct { - processorMap map[string]thrift.TProcessorFunction - handler AddService -} - -func (p *AddServiceProcessor) AddToProcessorMap(key string, processor thrift.TProcessorFunction) { - p.processorMap[key] = processor -} - -func (p *AddServiceProcessor) GetProcessorFunction(key string) (processor thrift.TProcessorFunction, ok bool) { - processor, ok = p.processorMap[key] - return processor, ok -} - -func (p *AddServiceProcessor) ProcessorMap() map[string]thrift.TProcessorFunction { - return p.processorMap -} - -func NewAddServiceProcessor(handler AddService) *AddServiceProcessor { - - self4 := &AddServiceProcessor{handler: handler, processorMap: make(map[string]thrift.TProcessorFunction)} - self4.processorMap["Sum"] = &addServiceProcessorSum{handler: handler} - self4.processorMap["Concat"] = &addServiceProcessorConcat{handler: handler} - return self4 -} - -func (p *AddServiceProcessor) Process(iprot, oprot thrift.TProtocol) (success bool, err thrift.TException) { - name, _, seqId, err := iprot.ReadMessageBegin() - if err != nil { - return false, err - } - if processor, ok := p.GetProcessorFunction(name); ok { - return processor.Process(seqId, iprot, oprot) - } - iprot.Skip(thrift.STRUCT) - iprot.ReadMessageEnd() - x5 := thrift.NewTApplicationException(thrift.UNKNOWN_METHOD, "Unknown function "+name) - oprot.WriteMessageBegin(name, thrift.EXCEPTION, seqId) - x5.Write(oprot) - oprot.WriteMessageEnd() - oprot.Flush() - return false, x5 - -} - -type addServiceProcessorSum struct { - handler AddService -} - -func (p *addServiceProcessorSum) Process(seqId int32, iprot, oprot thrift.TProtocol) (success bool, err thrift.TException) { - args := AddServiceSumArgs{} - if err = args.Read(iprot); err != nil { - iprot.ReadMessageEnd() - x := thrift.NewTApplicationException(thrift.PROTOCOL_ERROR, err.Error()) - oprot.WriteMessageBegin("Sum", thrift.EXCEPTION, seqId) - x.Write(oprot) - oprot.WriteMessageEnd() - oprot.Flush() - return false, err - } - - iprot.ReadMessageEnd() - result := AddServiceSumResult{} - var retval *SumReply - var err2 error - if retval, err2 = p.handler.Sum(args.A, args.B); err2 != nil { - x := thrift.NewTApplicationException(thrift.INTERNAL_ERROR, "Internal error processing Sum: "+err2.Error()) - oprot.WriteMessageBegin("Sum", thrift.EXCEPTION, seqId) - x.Write(oprot) - oprot.WriteMessageEnd() - oprot.Flush() - return true, err2 - } else { - result.Success = retval - } - if err2 = oprot.WriteMessageBegin("Sum", thrift.REPLY, seqId); err2 != nil { - err = err2 - } - if err2 = result.Write(oprot); err == nil && err2 != nil { - err = err2 - } - if err2 = oprot.WriteMessageEnd(); err == nil && err2 != nil { - err = err2 - } - if err2 = oprot.Flush(); err == nil && err2 != nil { - err = err2 - } - if err != nil { - return - } - return true, err -} - -type addServiceProcessorConcat struct { - handler AddService -} - -func (p *addServiceProcessorConcat) Process(seqId int32, iprot, oprot thrift.TProtocol) (success bool, err thrift.TException) { - args := AddServiceConcatArgs{} - if err = args.Read(iprot); err != nil { - iprot.ReadMessageEnd() - x := thrift.NewTApplicationException(thrift.PROTOCOL_ERROR, err.Error()) - oprot.WriteMessageBegin("Concat", thrift.EXCEPTION, seqId) - x.Write(oprot) - oprot.WriteMessageEnd() - oprot.Flush() - return false, err - } - - iprot.ReadMessageEnd() - result := AddServiceConcatResult{} - var retval *ConcatReply - var err2 error - if retval, err2 = p.handler.Concat(args.A, args.B); err2 != nil { - x := thrift.NewTApplicationException(thrift.INTERNAL_ERROR, "Internal error processing Concat: "+err2.Error()) - oprot.WriteMessageBegin("Concat", thrift.EXCEPTION, seqId) - x.Write(oprot) - oprot.WriteMessageEnd() - oprot.Flush() - return true, err2 - } else { - result.Success = retval - } - if err2 = oprot.WriteMessageBegin("Concat", thrift.REPLY, seqId); err2 != nil { - err = err2 - } - if err2 = result.Write(oprot); err == nil && err2 != nil { - err = err2 - } - if err2 = oprot.WriteMessageEnd(); err == nil && err2 != nil { - err = err2 - } - if err2 = oprot.Flush(); err == nil && err2 != nil { - err = err2 - } - if err != nil { - return - } - return true, err -} - -// HELPER FUNCTIONS AND STRUCTURES - -// Attributes: -// - A -// - B -type AddServiceSumArgs struct { - A int64 `thrift:"a,1" json:"a"` - B int64 `thrift:"b,2" json:"b"` -} - -func NewAddServiceSumArgs() *AddServiceSumArgs { - return &AddServiceSumArgs{} -} - -func (p *AddServiceSumArgs) GetA() int64 { - return p.A -} - -func (p *AddServiceSumArgs) GetB() int64 { - return p.B -} -func (p *AddServiceSumArgs) Read(iprot thrift.TProtocol) error { - if _, err := iprot.ReadStructBegin(); err != nil { - return thrift.PrependError(fmt.Sprintf("%T read error: ", p), err) - } - - for { - _, fieldTypeId, fieldId, err := iprot.ReadFieldBegin() - if err != nil { - return thrift.PrependError(fmt.Sprintf("%T field %d read error: ", p, fieldId), err) - } - if fieldTypeId == thrift.STOP { - break - } - switch fieldId { - case 1: - if err := p.readField1(iprot); err != nil { - return err - } - case 2: - if err := p.readField2(iprot); err != nil { - return err - } - default: - if err := iprot.Skip(fieldTypeId); err != nil { - return err - } - } - if err := iprot.ReadFieldEnd(); err != nil { - return err - } - } - if err := iprot.ReadStructEnd(); err != nil { - return thrift.PrependError(fmt.Sprintf("%T read struct end error: ", p), err) - } - return nil -} - -func (p *AddServiceSumArgs) readField1(iprot thrift.TProtocol) error { - if v, err := iprot.ReadI64(); err != nil { - return thrift.PrependError("error reading field 1: ", err) - } else { - p.A = v - } - return nil -} - -func (p *AddServiceSumArgs) readField2(iprot thrift.TProtocol) error { - if v, err := iprot.ReadI64(); err != nil { - return thrift.PrependError("error reading field 2: ", err) - } else { - p.B = v - } - return nil -} - -func (p *AddServiceSumArgs) Write(oprot thrift.TProtocol) error { - if err := oprot.WriteStructBegin("Sum_args"); err != nil { - return thrift.PrependError(fmt.Sprintf("%T write struct begin error: ", p), err) - } - if err := p.writeField1(oprot); err != nil { - return err - } - if err := p.writeField2(oprot); err != nil { - return err - } - if err := oprot.WriteFieldStop(); err != nil { - return thrift.PrependError("write field stop error: ", err) - } - if err := oprot.WriteStructEnd(); err != nil { - return thrift.PrependError("write struct stop error: ", err) - } - return nil -} - -func (p *AddServiceSumArgs) writeField1(oprot thrift.TProtocol) (err error) { - if err := oprot.WriteFieldBegin("a", thrift.I64, 1); err != nil { - return thrift.PrependError(fmt.Sprintf("%T write field begin error 1:a: ", p), err) - } - if err := oprot.WriteI64(int64(p.A)); err != nil { - return thrift.PrependError(fmt.Sprintf("%T.a (1) field write error: ", p), err) - } - if err := oprot.WriteFieldEnd(); err != nil { - return thrift.PrependError(fmt.Sprintf("%T write field end error 1:a: ", p), err) - } - return err -} - -func (p *AddServiceSumArgs) writeField2(oprot thrift.TProtocol) (err error) { - if err := oprot.WriteFieldBegin("b", thrift.I64, 2); err != nil { - return thrift.PrependError(fmt.Sprintf("%T write field begin error 2:b: ", p), err) - } - if err := oprot.WriteI64(int64(p.B)); err != nil { - return thrift.PrependError(fmt.Sprintf("%T.b (2) field write error: ", p), err) - } - if err := oprot.WriteFieldEnd(); err != nil { - return thrift.PrependError(fmt.Sprintf("%T write field end error 2:b: ", p), err) - } - return err -} - -func (p *AddServiceSumArgs) String() string { - if p == nil { - return "" - } - return fmt.Sprintf("AddServiceSumArgs(%+v)", *p) -} - -// Attributes: -// - Success -type AddServiceSumResult struct { - Success *SumReply `thrift:"success,0" json:"success,omitempty"` -} - -func NewAddServiceSumResult() *AddServiceSumResult { - return &AddServiceSumResult{} -} - -var AddServiceSumResult_Success_DEFAULT *SumReply - -func (p *AddServiceSumResult) GetSuccess() *SumReply { - if !p.IsSetSuccess() { - return AddServiceSumResult_Success_DEFAULT - } - return p.Success -} -func (p *AddServiceSumResult) IsSetSuccess() bool { - return p.Success != nil -} - -func (p *AddServiceSumResult) Read(iprot thrift.TProtocol) error { - if _, err := iprot.ReadStructBegin(); err != nil { - return thrift.PrependError(fmt.Sprintf("%T read error: ", p), err) - } - - for { - _, fieldTypeId, fieldId, err := iprot.ReadFieldBegin() - if err != nil { - return thrift.PrependError(fmt.Sprintf("%T field %d read error: ", p, fieldId), err) - } - if fieldTypeId == thrift.STOP { - break - } - switch fieldId { - case 0: - if err := p.readField0(iprot); err != nil { - return err - } - default: - if err := iprot.Skip(fieldTypeId); err != nil { - return err - } - } - if err := iprot.ReadFieldEnd(); err != nil { - return err - } - } - if err := iprot.ReadStructEnd(); err != nil { - return thrift.PrependError(fmt.Sprintf("%T read struct end error: ", p), err) - } - return nil -} - -func (p *AddServiceSumResult) readField0(iprot thrift.TProtocol) error { - p.Success = &SumReply{} - if err := p.Success.Read(iprot); err != nil { - return thrift.PrependError(fmt.Sprintf("%T error reading struct: ", p.Success), err) - } - return nil -} - -func (p *AddServiceSumResult) Write(oprot thrift.TProtocol) error { - if err := oprot.WriteStructBegin("Sum_result"); err != nil { - return thrift.PrependError(fmt.Sprintf("%T write struct begin error: ", p), err) - } - if err := p.writeField0(oprot); err != nil { - return err - } - if err := oprot.WriteFieldStop(); err != nil { - return thrift.PrependError("write field stop error: ", err) - } - if err := oprot.WriteStructEnd(); err != nil { - return thrift.PrependError("write struct stop error: ", err) - } - return nil -} - -func (p *AddServiceSumResult) writeField0(oprot thrift.TProtocol) (err error) { - if p.IsSetSuccess() { - if err := oprot.WriteFieldBegin("success", thrift.STRUCT, 0); err != nil { - return thrift.PrependError(fmt.Sprintf("%T write field begin error 0:success: ", p), err) - } - if err := p.Success.Write(oprot); err != nil { - return thrift.PrependError(fmt.Sprintf("%T error writing struct: ", p.Success), err) - } - if err := oprot.WriteFieldEnd(); err != nil { - return thrift.PrependError(fmt.Sprintf("%T write field end error 0:success: ", p), err) - } - } - return err -} - -func (p *AddServiceSumResult) String() string { - if p == nil { - return "" - } - return fmt.Sprintf("AddServiceSumResult(%+v)", *p) -} - -// Attributes: -// - A -// - B -type AddServiceConcatArgs struct { - A string `thrift:"a,1" json:"a"` - B string `thrift:"b,2" json:"b"` -} - -func NewAddServiceConcatArgs() *AddServiceConcatArgs { - return &AddServiceConcatArgs{} -} - -func (p *AddServiceConcatArgs) GetA() string { - return p.A -} - -func (p *AddServiceConcatArgs) GetB() string { - return p.B -} -func (p *AddServiceConcatArgs) Read(iprot thrift.TProtocol) error { - if _, err := iprot.ReadStructBegin(); err != nil { - return thrift.PrependError(fmt.Sprintf("%T read error: ", p), err) - } - - for { - _, fieldTypeId, fieldId, err := iprot.ReadFieldBegin() - if err != nil { - return thrift.PrependError(fmt.Sprintf("%T field %d read error: ", p, fieldId), err) - } - if fieldTypeId == thrift.STOP { - break - } - switch fieldId { - case 1: - if err := p.readField1(iprot); err != nil { - return err - } - case 2: - if err := p.readField2(iprot); err != nil { - return err - } - default: - if err := iprot.Skip(fieldTypeId); err != nil { - return err - } - } - if err := iprot.ReadFieldEnd(); err != nil { - return err - } - } - if err := iprot.ReadStructEnd(); err != nil { - return thrift.PrependError(fmt.Sprintf("%T read struct end error: ", p), err) - } - return nil -} - -func (p *AddServiceConcatArgs) readField1(iprot thrift.TProtocol) error { - if v, err := iprot.ReadString(); err != nil { - return thrift.PrependError("error reading field 1: ", err) - } else { - p.A = v - } - return nil -} - -func (p *AddServiceConcatArgs) readField2(iprot thrift.TProtocol) error { - if v, err := iprot.ReadString(); err != nil { - return thrift.PrependError("error reading field 2: ", err) - } else { - p.B = v - } - return nil -} - -func (p *AddServiceConcatArgs) Write(oprot thrift.TProtocol) error { - if err := oprot.WriteStructBegin("Concat_args"); err != nil { - return thrift.PrependError(fmt.Sprintf("%T write struct begin error: ", p), err) - } - if err := p.writeField1(oprot); err != nil { - return err - } - if err := p.writeField2(oprot); err != nil { - return err - } - if err := oprot.WriteFieldStop(); err != nil { - return thrift.PrependError("write field stop error: ", err) - } - if err := oprot.WriteStructEnd(); err != nil { - return thrift.PrependError("write struct stop error: ", err) - } - return nil -} - -func (p *AddServiceConcatArgs) writeField1(oprot thrift.TProtocol) (err error) { - if err := oprot.WriteFieldBegin("a", thrift.STRING, 1); err != nil { - return thrift.PrependError(fmt.Sprintf("%T write field begin error 1:a: ", p), err) - } - if err := oprot.WriteString(string(p.A)); err != nil { - return thrift.PrependError(fmt.Sprintf("%T.a (1) field write error: ", p), err) - } - if err := oprot.WriteFieldEnd(); err != nil { - return thrift.PrependError(fmt.Sprintf("%T write field end error 1:a: ", p), err) - } - return err -} - -func (p *AddServiceConcatArgs) writeField2(oprot thrift.TProtocol) (err error) { - if err := oprot.WriteFieldBegin("b", thrift.STRING, 2); err != nil { - return thrift.PrependError(fmt.Sprintf("%T write field begin error 2:b: ", p), err) - } - if err := oprot.WriteString(string(p.B)); err != nil { - return thrift.PrependError(fmt.Sprintf("%T.b (2) field write error: ", p), err) - } - if err := oprot.WriteFieldEnd(); err != nil { - return thrift.PrependError(fmt.Sprintf("%T write field end error 2:b: ", p), err) - } - return err -} - -func (p *AddServiceConcatArgs) String() string { - if p == nil { - return "" - } - return fmt.Sprintf("AddServiceConcatArgs(%+v)", *p) -} - -// Attributes: -// - Success -type AddServiceConcatResult struct { - Success *ConcatReply `thrift:"success,0" json:"success,omitempty"` -} - -func NewAddServiceConcatResult() *AddServiceConcatResult { - return &AddServiceConcatResult{} -} - -var AddServiceConcatResult_Success_DEFAULT *ConcatReply - -func (p *AddServiceConcatResult) GetSuccess() *ConcatReply { - if !p.IsSetSuccess() { - return AddServiceConcatResult_Success_DEFAULT - } - return p.Success -} -func (p *AddServiceConcatResult) IsSetSuccess() bool { - return p.Success != nil -} - -func (p *AddServiceConcatResult) Read(iprot thrift.TProtocol) error { - if _, err := iprot.ReadStructBegin(); err != nil { - return thrift.PrependError(fmt.Sprintf("%T read error: ", p), err) - } - - for { - _, fieldTypeId, fieldId, err := iprot.ReadFieldBegin() - if err != nil { - return thrift.PrependError(fmt.Sprintf("%T field %d read error: ", p, fieldId), err) - } - if fieldTypeId == thrift.STOP { - break - } - switch fieldId { - case 0: - if err := p.readField0(iprot); err != nil { - return err - } - default: - if err := iprot.Skip(fieldTypeId); err != nil { - return err - } - } - if err := iprot.ReadFieldEnd(); err != nil { - return err - } - } - if err := iprot.ReadStructEnd(); err != nil { - return thrift.PrependError(fmt.Sprintf("%T read struct end error: ", p), err) - } - return nil -} - -func (p *AddServiceConcatResult) readField0(iprot thrift.TProtocol) error { - p.Success = &ConcatReply{} - if err := p.Success.Read(iprot); err != nil { - return thrift.PrependError(fmt.Sprintf("%T error reading struct: ", p.Success), err) - } - return nil -} - -func (p *AddServiceConcatResult) Write(oprot thrift.TProtocol) error { - if err := oprot.WriteStructBegin("Concat_result"); err != nil { - return thrift.PrependError(fmt.Sprintf("%T write struct begin error: ", p), err) - } - if err := p.writeField0(oprot); err != nil { - return err - } - if err := oprot.WriteFieldStop(); err != nil { - return thrift.PrependError("write field stop error: ", err) - } - if err := oprot.WriteStructEnd(); err != nil { - return thrift.PrependError("write struct stop error: ", err) - } - return nil -} - -func (p *AddServiceConcatResult) writeField0(oprot thrift.TProtocol) (err error) { - if p.IsSetSuccess() { - if err := oprot.WriteFieldBegin("success", thrift.STRUCT, 0); err != nil { - return thrift.PrependError(fmt.Sprintf("%T write field begin error 0:success: ", p), err) - } - if err := p.Success.Write(oprot); err != nil { - return thrift.PrependError(fmt.Sprintf("%T error writing struct: ", p.Success), err) - } - if err := oprot.WriteFieldEnd(); err != nil { - return thrift.PrependError(fmt.Sprintf("%T write field end error 0:success: ", p), err) - } - } - return err -} - -func (p *AddServiceConcatResult) String() string { - if p == nil { - return "" - } - return fmt.Sprintf("AddServiceConcatResult(%+v)", *p) -} diff --git a/examples/addsvc2/thrift/gen-go/addsvc/constants.go b/examples/addsvc2/thrift/gen-go/addsvc/constants.go deleted file mode 100644 index 2f0079acc..000000000 --- a/examples/addsvc2/thrift/gen-go/addsvc/constants.go +++ /dev/null @@ -1,18 +0,0 @@ -// Autogenerated by Thrift Compiler (0.9.3) -// DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING - -package addsvc - -import ( - "bytes" - "fmt" - "github.com/apache/thrift/lib/go/thrift" -) - -// (needed to ensure safety because of naive import list construction.) -var _ = thrift.ZERO -var _ = fmt.Printf -var _ = bytes.Equal - -func init() { -} diff --git a/examples/addsvc2/thrift/gen-go/addsvc/ttypes.go b/examples/addsvc2/thrift/gen-go/addsvc/ttypes.go deleted file mode 100644 index 2fcbd55ea..000000000 --- a/examples/addsvc2/thrift/gen-go/addsvc/ttypes.go +++ /dev/null @@ -1,269 +0,0 @@ -// Autogenerated by Thrift Compiler (0.9.3) -// DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING - -package addsvc - -import ( - "bytes" - "fmt" - "github.com/apache/thrift/lib/go/thrift" -) - -// (needed to ensure safety because of naive import list construction.) -var _ = thrift.ZERO -var _ = fmt.Printf -var _ = bytes.Equal - -var GoUnusedProtection__ int - -// Attributes: -// - Value -// - Err -type SumReply struct { - Value int64 `thrift:"value,1" json:"value"` - Err string `thrift:"err,2" json:"err"` -} - -func NewSumReply() *SumReply { - return &SumReply{} -} - -func (p *SumReply) GetValue() int64 { - return p.Value -} - -func (p *SumReply) GetErr() string { - return p.Err -} -func (p *SumReply) Read(iprot thrift.TProtocol) error { - if _, err := iprot.ReadStructBegin(); err != nil { - return thrift.PrependError(fmt.Sprintf("%T read error: ", p), err) - } - - for { - _, fieldTypeId, fieldId, err := iprot.ReadFieldBegin() - if err != nil { - return thrift.PrependError(fmt.Sprintf("%T field %d read error: ", p, fieldId), err) - } - if fieldTypeId == thrift.STOP { - break - } - switch fieldId { - case 1: - if err := p.readField1(iprot); err != nil { - return err - } - case 2: - if err := p.readField2(iprot); err != nil { - return err - } - default: - if err := iprot.Skip(fieldTypeId); err != nil { - return err - } - } - if err := iprot.ReadFieldEnd(); err != nil { - return err - } - } - if err := iprot.ReadStructEnd(); err != nil { - return thrift.PrependError(fmt.Sprintf("%T read struct end error: ", p), err) - } - return nil -} - -func (p *SumReply) readField1(iprot thrift.TProtocol) error { - if v, err := iprot.ReadI64(); err != nil { - return thrift.PrependError("error reading field 1: ", err) - } else { - p.Value = v - } - return nil -} - -func (p *SumReply) readField2(iprot thrift.TProtocol) error { - if v, err := iprot.ReadString(); err != nil { - return thrift.PrependError("error reading field 2: ", err) - } else { - p.Err = v - } - return nil -} - -func (p *SumReply) Write(oprot thrift.TProtocol) error { - if err := oprot.WriteStructBegin("SumReply"); err != nil { - return thrift.PrependError(fmt.Sprintf("%T write struct begin error: ", p), err) - } - if err := p.writeField1(oprot); err != nil { - return err - } - if err := p.writeField2(oprot); err != nil { - return err - } - if err := oprot.WriteFieldStop(); err != nil { - return thrift.PrependError("write field stop error: ", err) - } - if err := oprot.WriteStructEnd(); err != nil { - return thrift.PrependError("write struct stop error: ", err) - } - return nil -} - -func (p *SumReply) writeField1(oprot thrift.TProtocol) (err error) { - if err := oprot.WriteFieldBegin("value", thrift.I64, 1); err != nil { - return thrift.PrependError(fmt.Sprintf("%T write field begin error 1:value: ", p), err) - } - if err := oprot.WriteI64(int64(p.Value)); err != nil { - return thrift.PrependError(fmt.Sprintf("%T.value (1) field write error: ", p), err) - } - if err := oprot.WriteFieldEnd(); err != nil { - return thrift.PrependError(fmt.Sprintf("%T write field end error 1:value: ", p), err) - } - return err -} - -func (p *SumReply) writeField2(oprot thrift.TProtocol) (err error) { - if err := oprot.WriteFieldBegin("err", thrift.STRING, 2); err != nil { - return thrift.PrependError(fmt.Sprintf("%T write field begin error 2:err: ", p), err) - } - if err := oprot.WriteString(string(p.Err)); err != nil { - return thrift.PrependError(fmt.Sprintf("%T.err (2) field write error: ", p), err) - } - if err := oprot.WriteFieldEnd(); err != nil { - return thrift.PrependError(fmt.Sprintf("%T write field end error 2:err: ", p), err) - } - return err -} - -func (p *SumReply) String() string { - if p == nil { - return "" - } - return fmt.Sprintf("SumReply(%+v)", *p) -} - -// Attributes: -// - Value -// - Err -type ConcatReply struct { - Value string `thrift:"value,1" json:"value"` - Err string `thrift:"err,2" json:"err"` -} - -func NewConcatReply() *ConcatReply { - return &ConcatReply{} -} - -func (p *ConcatReply) GetValue() string { - return p.Value -} - -func (p *ConcatReply) GetErr() string { - return p.Err -} -func (p *ConcatReply) Read(iprot thrift.TProtocol) error { - if _, err := iprot.ReadStructBegin(); err != nil { - return thrift.PrependError(fmt.Sprintf("%T read error: ", p), err) - } - - for { - _, fieldTypeId, fieldId, err := iprot.ReadFieldBegin() - if err != nil { - return thrift.PrependError(fmt.Sprintf("%T field %d read error: ", p, fieldId), err) - } - if fieldTypeId == thrift.STOP { - break - } - switch fieldId { - case 1: - if err := p.readField1(iprot); err != nil { - return err - } - case 2: - if err := p.readField2(iprot); err != nil { - return err - } - default: - if err := iprot.Skip(fieldTypeId); err != nil { - return err - } - } - if err := iprot.ReadFieldEnd(); err != nil { - return err - } - } - if err := iprot.ReadStructEnd(); err != nil { - return thrift.PrependError(fmt.Sprintf("%T read struct end error: ", p), err) - } - return nil -} - -func (p *ConcatReply) readField1(iprot thrift.TProtocol) error { - if v, err := iprot.ReadString(); err != nil { - return thrift.PrependError("error reading field 1: ", err) - } else { - p.Value = v - } - return nil -} - -func (p *ConcatReply) readField2(iprot thrift.TProtocol) error { - if v, err := iprot.ReadString(); err != nil { - return thrift.PrependError("error reading field 2: ", err) - } else { - p.Err = v - } - return nil -} - -func (p *ConcatReply) Write(oprot thrift.TProtocol) error { - if err := oprot.WriteStructBegin("ConcatReply"); err != nil { - return thrift.PrependError(fmt.Sprintf("%T write struct begin error: ", p), err) - } - if err := p.writeField1(oprot); err != nil { - return err - } - if err := p.writeField2(oprot); err != nil { - return err - } - if err := oprot.WriteFieldStop(); err != nil { - return thrift.PrependError("write field stop error: ", err) - } - if err := oprot.WriteStructEnd(); err != nil { - return thrift.PrependError("write struct stop error: ", err) - } - return nil -} - -func (p *ConcatReply) writeField1(oprot thrift.TProtocol) (err error) { - if err := oprot.WriteFieldBegin("value", thrift.STRING, 1); err != nil { - return thrift.PrependError(fmt.Sprintf("%T write field begin error 1:value: ", p), err) - } - if err := oprot.WriteString(string(p.Value)); err != nil { - return thrift.PrependError(fmt.Sprintf("%T.value (1) field write error: ", p), err) - } - if err := oprot.WriteFieldEnd(); err != nil { - return thrift.PrependError(fmt.Sprintf("%T write field end error 1:value: ", p), err) - } - return err -} - -func (p *ConcatReply) writeField2(oprot thrift.TProtocol) (err error) { - if err := oprot.WriteFieldBegin("err", thrift.STRING, 2); err != nil { - return thrift.PrependError(fmt.Sprintf("%T write field begin error 2:err: ", p), err) - } - if err := oprot.WriteString(string(p.Err)); err != nil { - return thrift.PrependError(fmt.Sprintf("%T.err (2) field write error: ", p), err) - } - if err := oprot.WriteFieldEnd(); err != nil { - return thrift.PrependError(fmt.Sprintf("%T write field end error 2:err: ", p), err) - } - return err -} - -func (p *ConcatReply) String() string { - if p == nil { - return "" - } - return fmt.Sprintf("ConcatReply(%+v)", *p) -} From ec9f2b6a067750606a84520652a5c0a1d2223f25 Mon Sep 17 00:00:00 2001 From: Peter Bourgon Date: Mon, 17 Jul 2017 19:22:43 -0700 Subject: [PATCH 7/9] examples/apigateway: fix for new addsvc --- examples/apigateway/main.go | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/examples/apigateway/main.go b/examples/apigateway/main.go index bba617818..3b4cd675e 100644 --- a/examples/apigateway/main.go +++ b/examples/apigateway/main.go @@ -16,19 +16,21 @@ import ( "syscall" "time" + consulsd "github.com/go-kit/kit/sd/consul" "github.com/gorilla/mux" "github.com/hashicorp/consul/api" stdopentracing "github.com/opentracing/opentracing-go" + "google.golang.org/grpc" "github.com/go-kit/kit/endpoint" - "github.com/go-kit/kit/examples/addsvc" - addsvcgrpcclient "github.com/go-kit/kit/examples/addsvc/client/grpc" "github.com/go-kit/kit/log" "github.com/go-kit/kit/sd" - consulsd "github.com/go-kit/kit/sd/consul" "github.com/go-kit/kit/sd/lb" httptransport "github.com/go-kit/kit/transport/http" - "google.golang.org/grpc" + + "github.com/go-kit/kit/examples/addsvc/pkg/addendpoint" + "github.com/go-kit/kit/examples/addsvc/pkg/addservice" + "github.com/go-kit/kit/examples/addsvc/pkg/addtransport" ) func main() { @@ -79,22 +81,21 @@ func main() { // addsvc client package to construct a complete service. We can then // leverage the addsvc.Make{Sum,Concat}Endpoint constructors to convert // the complete service to specific endpoint. - var ( tags = []string{} passingOnly = true - endpoints = addsvc.Endpoints{} + endpoints = addendpoint.Set{} instancer = consulsd.NewInstancer(client, logger, "addsvc", tags, passingOnly) ) { - factory := addsvcFactory(addsvc.MakeSumEndpoint, tracer, logger) + factory := addsvcFactory(addendpoint.MakeSumEndpoint, tracer, logger) endpointer := sd.NewEndpointer(instancer, factory, logger) balancer := lb.NewRoundRobin(endpointer) retry := lb.Retry(*retryMax, *retryTimeout, balancer) endpoints.SumEndpoint = retry } { - factory := addsvcFactory(addsvc.MakeConcatEndpoint, tracer, logger) + factory := addsvcFactory(addendpoint.MakeConcatEndpoint, tracer, logger) endpointer := sd.NewEndpointer(instancer, factory, logger) balancer := lb.NewRoundRobin(endpointer) retry := lb.Retry(*retryMax, *retryTimeout, balancer) @@ -105,7 +106,7 @@ func main() { // HTTP handler, and just install it under a particular path prefix in // our router. - r.PathPrefix("/addsvc").Handler(http.StripPrefix("/addsvc", addsvc.MakeHTTPHandler(endpoints, tracer, logger))) + r.PathPrefix("/addsvc").Handler(http.StripPrefix("/addsvc", addtransport.NewHTTPHandler(endpoints, tracer, logger))) } // stringsvc routes. @@ -164,7 +165,7 @@ func main() { logger.Log("exit", <-errc) } -func addsvcFactory(makeEndpoint func(addsvc.Service) endpoint.Endpoint, tracer stdopentracing.Tracer, logger log.Logger) sd.Factory { +func addsvcFactory(makeEndpoint func(addservice.Service) endpoint.Endpoint, tracer stdopentracing.Tracer, logger log.Logger) sd.Factory { return func(instance string) (endpoint.Endpoint, io.Closer, error) { // We could just as easily use the HTTP or Thrift client package to make // the connection to addsvc. We've chosen gRPC arbitrarily. Note that @@ -175,7 +176,7 @@ func addsvcFactory(makeEndpoint func(addsvc.Service) endpoint.Endpoint, tracer s if err != nil { return nil, nil, err } - service := addsvcgrpcclient.New(conn, tracer, logger) + service := addtransport.NewGRPCClient(conn, tracer, logger) endpoint := makeEndpoint(service) // Notice that the addsvc gRPC client converts the connection to a From b245d894318f73a6a6a2a1b64cdb580c3b219894 Mon Sep 17 00:00:00 2001 From: Peter Bourgon Date: Mon, 17 Jul 2017 19:55:15 -0700 Subject: [PATCH 8/9] circle.yml: go get test deps also --- circle.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/circle.yml b/circle.yml index ad9e45af3..29520e694 100644 --- a/circle.yml +++ b/circle.yml @@ -17,7 +17,7 @@ test: - mkdir -p /home/ubuntu/.go_workspace/src/github.com/go-kit - mv /home/ubuntu/kit /home/ubuntu/.go_workspace/src/github.com/go-kit - ln -s /home/ubuntu/.go_workspace/src/github.com/go-kit/kit /home/ubuntu/kit - - go get github.com/go-kit/kit/... + - go get -t github.com/go-kit/kit/... override: - go test -v -race -tags integration github.com/go-kit/kit/...: environment: From 8b79fcceaa3ebba857d2e1743fb067fbe08f9cc7 Mon Sep 17 00:00:00 2001 From: Peter Bourgon Date: Tue, 18 Jul 2017 18:27:03 -0700 Subject: [PATCH 9/9] examples/addsvc: README and other documentation --- examples/addsvc/README.md | 17 +++++++++++++++++ examples/addsvc/pkg/addtransport/grpc.go | 3 ++- examples/addsvc/pkg/addtransport/http.go | 3 ++- examples/addsvc/pkg/addtransport/thrift.go | 3 ++- 4 files changed, 23 insertions(+), 3 deletions(-) create mode 100644 examples/addsvc/README.md diff --git a/examples/addsvc/README.md b/examples/addsvc/README.md new file mode 100644 index 000000000..080800609 --- /dev/null +++ b/examples/addsvc/README.md @@ -0,0 +1,17 @@ +# addsvc + +addsvc is an example microservice which takes full advantage of most of Go +kit's features, including both service- and transport-level middlewares, +speaking multiple transports simultaneously, distributed tracing, and rich +error definitions. The server binary is available in cmd/addsvc. The client +binary is available in cmd/addcli. + +Finally, the addtransport package provides both server and clients for each +supported transport. The client structs bake-in certain middlewares, in order to +demonstrate the _client library pattern_. But beware: client libraries are +generally a bad idea, because they easily lead to the + [distributed monolith antipattern](https://www.microservices.com/talks/dont-build-a-distributed-monolith/). +If you don't _know_ you need to use one in your organization, it's probably best +avoided: prefer moving that logic to consumers, and relying on + [contract testing](https://docs.pact.io/best_practices/contract_tests_not_functional_tests.html) +to detect incompatibilities. diff --git a/examples/addsvc/pkg/addtransport/grpc.go b/examples/addsvc/pkg/addtransport/grpc.go index 82e9dd6e1..cfb4243b7 100644 --- a/examples/addsvc/pkg/addtransport/grpc.go +++ b/examples/addsvc/pkg/addtransport/grpc.go @@ -68,7 +68,8 @@ func (s *grpcServer) Concat(ctx oldcontext.Context, req *pb.ConcatRequest) (*pb. // NewGRPCClient returns an AddService backed by a gRPC server at the other end // of the conn. The caller is responsible for constructing the conn, and -// eventually closing the underlying transport. +// eventually closing the underlying transport. We bake-in certain middlewares, +// implementing the client library pattern. func NewGRPCClient(conn *grpc.ClientConn, tracer stdopentracing.Tracer, logger log.Logger) addservice.Service { // We construct a single ratelimiter middleware, to limit the total outgoing // QPS from this client to all methods on the remote instance. We also diff --git a/examples/addsvc/pkg/addtransport/http.go b/examples/addsvc/pkg/addtransport/http.go index ad25e4f32..9759d157b 100644 --- a/examples/addsvc/pkg/addtransport/http.go +++ b/examples/addsvc/pkg/addtransport/http.go @@ -51,7 +51,8 @@ func NewHTTPHandler(endpoints addendpoint.Set, tracer stdopentracing.Tracer, log // NewHTTPClient returns an AddService backed by an HTTP server living at the // remote instance. We expect instance to come from a service discovery system, -// so likely of the form "host:port". +// so likely of the form "host:port". We bake-in certain middlewares, +// implementing the client library pattern. func NewHTTPClient(instance string, tracer stdopentracing.Tracer, logger log.Logger) (addservice.Service, error) { // Quickly sanitize the instance string. if !strings.HasPrefix(instance, "http") { diff --git a/examples/addsvc/pkg/addtransport/thrift.go b/examples/addsvc/pkg/addtransport/thrift.go index 4de44ba09..cf7151428 100644 --- a/examples/addsvc/pkg/addtransport/thrift.go +++ b/examples/addsvc/pkg/addtransport/thrift.go @@ -51,7 +51,8 @@ func (s *thriftServer) Concat(a string, b string) (*addthrift.ConcatReply, error // NewThriftClient returns an AddService backed by a Thrift server described by // the provided client. The caller is responsible for constructing the client, -// and eventually closing the underlying transport. +// and eventually closing the underlying transport. We bake-in certain middlewares, +// implementing the client library pattern. func NewThriftClient(client *addthrift.AddServiceClient) addservice.Service { // We construct a single ratelimiter middleware, to limit the total outgoing // QPS from this client to all methods on the remote instance. We also