package addendpoint import ( "context" "time" "golang.org/x/time/rate" stdopentracing "github.com/opentracing/opentracing-go" stdzipkin "github.com/openzipkin/zipkin-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/tracing/zipkin" "github.com/go-kit/kit/examples/addsvc/pkg/addservice" ) // 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 addservice.Service, logger log.Logger, duration metrics.Histogram, otTracer stdopentracing.Tracer, zipkinTracer *stdzipkin.Tracer) Set { var sumEndpoint endpoint.Endpoint { sumEndpoint = MakeSumEndpoint(svc) sumEndpoint = ratelimit.NewErroringLimiter(rate.NewLimiter(rate.Every(time.Second), 1))(sumEndpoint) sumEndpoint = circuitbreaker.Gobreaker(gobreaker.NewCircuitBreaker(gobreaker.Settings{}))(sumEndpoint) sumEndpoint = opentracing.TraceServer(otTracer, "Sum")(sumEndpoint) sumEndpoint = zipkin.TraceEndpoint(zipkinTracer, "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.NewErroringLimiter(rate.NewLimiter(rate.Every(time.Second), 100))(concatEndpoint) concatEndpoint = circuitbreaker.Gobreaker(gobreaker.NewCircuitBreaker(gobreaker.Settings{}))(concatEndpoint) concatEndpoint = opentracing.TraceServer(otTracer, "Concat")(concatEndpoint) concatEndpoint = zipkin.TraceEndpoint(zipkinTracer, "Concat")(concatEndpoint) concatEndpoint = LoggingMiddleware(log.With(logger, "method", "Concat"))(concatEndpoint) concatEndpoint = InstrumentingMiddleware(duration.With("method", "Concat"))(concatEndpoint) } return Set{ SumEndpoint: sumEndpoint, ConcatEndpoint: concatEndpoint, } } // 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 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) return SumResponse{V: v, Err: err}, nil } } // MakeConcatEndpoint constructs a Concat endpoint wrapping the service. 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) return ConcatResponse{V: v, Err: err}, nil } } // compile time assertions for our response types implementing endpoint.Failer. var ( _ endpoint.Failer = SumResponse{} _ endpoint.Failer = ConcatResponse{} ) // 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 endpoint.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 endpoint.Failer. func (r ConcatResponse) Failed() error { return r.Err }