package addendpoint
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/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, 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,
}
}
// 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
}
}
// 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 }