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)
// Sum is limited to 1 request per second with burst of 1 request.
// Note, rate is defined as a time interval between requests.
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)
if zipkinTracer != nil {
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)
// Concat is limited to 1 request per second with burst of 100 requests.
// Note, rate is defined as a number of requests per second.
concatEndpoint = ratelimit.NewErroringLimiter(rate.NewLimiter(rate.Limit(1), 100))(concatEndpoint)
concatEndpoint = circuitbreaker.Gobreaker(gobreaker.NewCircuitBreaker(gobreaker.Settings{}))(concatEndpoint)
concatEndpoint = opentracing.TraceServer(otTracer, "Concat")(concatEndpoint)
if zipkinTracer != nil {
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 }