Moved to google.golang.org/genproto/googleapis/api/annotations
Fixes #52
This commit is contained in:
10
vendor/github.com/go-kit/kit/circuitbreaker/doc.go
generated
vendored
Normal file
10
vendor/github.com/go-kit/kit/circuitbreaker/doc.go
generated
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
// Package circuitbreaker implements the circuit breaker pattern.
|
||||
//
|
||||
// Circuit breakers prevent thundering herds, and improve resiliency against
|
||||
// intermittent errors. Every client-side endpoint should be wrapped in a
|
||||
// circuit breaker.
|
||||
//
|
||||
// We provide several implementations in this package, but if you're looking
|
||||
// for guidance, Gobreaker is probably the best place to start. It has a
|
||||
// simple and intuitive API, and is well-tested.
|
||||
package circuitbreaker
|
22
vendor/github.com/go-kit/kit/circuitbreaker/gobreaker.go
generated
vendored
Normal file
22
vendor/github.com/go-kit/kit/circuitbreaker/gobreaker.go
generated
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
package circuitbreaker
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/sony/gobreaker"
|
||||
|
||||
"github.com/go-kit/kit/endpoint"
|
||||
)
|
||||
|
||||
// Gobreaker returns an endpoint.Middleware that implements the circuit
|
||||
// breaker pattern using the sony/gobreaker package. Only errors returned by
|
||||
// the wrapped endpoint count against the circuit breaker's error count.
|
||||
//
|
||||
// See http://godoc.org/github.com/sony/gobreaker for more information.
|
||||
func Gobreaker(cb *gobreaker.CircuitBreaker) endpoint.Middleware {
|
||||
return func(next endpoint.Endpoint) endpoint.Endpoint {
|
||||
return func(ctx context.Context, request interface{}) (interface{}, error) {
|
||||
return cb.Execute(func() (interface{}, error) { return next(ctx, request) })
|
||||
}
|
||||
}
|
||||
}
|
19
vendor/github.com/go-kit/kit/circuitbreaker/gobreaker_test.go
generated
vendored
Normal file
19
vendor/github.com/go-kit/kit/circuitbreaker/gobreaker_test.go
generated
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
package circuitbreaker_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/sony/gobreaker"
|
||||
|
||||
"github.com/go-kit/kit/circuitbreaker"
|
||||
)
|
||||
|
||||
func TestGobreaker(t *testing.T) {
|
||||
var (
|
||||
breaker = circuitbreaker.Gobreaker(gobreaker.NewCircuitBreaker(gobreaker.Settings{}))
|
||||
primeWith = 100
|
||||
shouldPass = func(n int) bool { return n <= 5 } // https://github.com/sony/gobreaker/blob/bfa846d/gobreaker.go#L76
|
||||
circuitOpenError = "circuit breaker is open"
|
||||
)
|
||||
testFailingEndpoint(t, breaker, primeWith, shouldPass, 0, circuitOpenError)
|
||||
}
|
38
vendor/github.com/go-kit/kit/circuitbreaker/handy_breaker.go
generated
vendored
Normal file
38
vendor/github.com/go-kit/kit/circuitbreaker/handy_breaker.go
generated
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
package circuitbreaker
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/streadway/handy/breaker"
|
||||
|
||||
"github.com/go-kit/kit/endpoint"
|
||||
)
|
||||
|
||||
// HandyBreaker returns an endpoint.Middleware that implements the circuit
|
||||
// breaker pattern using the streadway/handy/breaker package. Only errors
|
||||
// returned by the wrapped endpoint count against the circuit breaker's error
|
||||
// count.
|
||||
//
|
||||
// See http://godoc.org/github.com/streadway/handy/breaker for more
|
||||
// information.
|
||||
func HandyBreaker(cb breaker.Breaker) endpoint.Middleware {
|
||||
return func(next endpoint.Endpoint) endpoint.Endpoint {
|
||||
return func(ctx context.Context, request interface{}) (response interface{}, err error) {
|
||||
if !cb.Allow() {
|
||||
return nil, breaker.ErrCircuitOpen
|
||||
}
|
||||
|
||||
defer func(begin time.Time) {
|
||||
if err == nil {
|
||||
cb.Success(time.Since(begin))
|
||||
} else {
|
||||
cb.Failure(time.Since(begin))
|
||||
}
|
||||
}(time.Now())
|
||||
|
||||
response, err = next(ctx, request)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
20
vendor/github.com/go-kit/kit/circuitbreaker/handy_breaker_test.go
generated
vendored
Normal file
20
vendor/github.com/go-kit/kit/circuitbreaker/handy_breaker_test.go
generated
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
package circuitbreaker_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
handybreaker "github.com/streadway/handy/breaker"
|
||||
|
||||
"github.com/go-kit/kit/circuitbreaker"
|
||||
)
|
||||
|
||||
func TestHandyBreaker(t *testing.T) {
|
||||
var (
|
||||
failureRatio = 0.05
|
||||
breaker = circuitbreaker.HandyBreaker(handybreaker.NewBreaker(failureRatio))
|
||||
primeWith = handybreaker.DefaultMinObservations * 10
|
||||
shouldPass = func(n int) bool { return (float64(n) / float64(primeWith+n)) <= failureRatio }
|
||||
openCircuitError = handybreaker.ErrCircuitOpen.Error()
|
||||
)
|
||||
testFailingEndpoint(t, breaker, primeWith, shouldPass, 0, openCircuitError)
|
||||
}
|
31
vendor/github.com/go-kit/kit/circuitbreaker/hystrix.go
generated
vendored
Normal file
31
vendor/github.com/go-kit/kit/circuitbreaker/hystrix.go
generated
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
package circuitbreaker
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/afex/hystrix-go/hystrix"
|
||||
|
||||
"github.com/go-kit/kit/endpoint"
|
||||
)
|
||||
|
||||
// Hystrix returns an endpoint.Middleware that implements the circuit
|
||||
// breaker pattern using the afex/hystrix-go package.
|
||||
//
|
||||
// When using this circuit breaker, please configure your commands separately.
|
||||
//
|
||||
// See https://godoc.org/github.com/afex/hystrix-go/hystrix for more
|
||||
// information.
|
||||
func Hystrix(commandName string) endpoint.Middleware {
|
||||
return func(next endpoint.Endpoint) endpoint.Endpoint {
|
||||
return func(ctx context.Context, request interface{}) (response interface{}, err error) {
|
||||
var resp interface{}
|
||||
if err := hystrix.Do(commandName, func() (err error) {
|
||||
resp, err = next(ctx, request)
|
||||
return err
|
||||
}, nil); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return resp, nil
|
||||
}
|
||||
}
|
||||
}
|
40
vendor/github.com/go-kit/kit/circuitbreaker/hystrix_test.go
generated
vendored
Normal file
40
vendor/github.com/go-kit/kit/circuitbreaker/hystrix_test.go
generated
vendored
Normal file
@@ -0,0 +1,40 @@
|
||||
package circuitbreaker_test
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
stdlog "log"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/afex/hystrix-go/hystrix"
|
||||
|
||||
"github.com/go-kit/kit/circuitbreaker"
|
||||
)
|
||||
|
||||
func TestHystrix(t *testing.T) {
|
||||
stdlog.SetOutput(ioutil.Discard)
|
||||
|
||||
const (
|
||||
commandName = "my-endpoint"
|
||||
errorPercent = 5
|
||||
maxConcurrent = 1000
|
||||
)
|
||||
hystrix.ConfigureCommand(commandName, hystrix.CommandConfig{
|
||||
ErrorPercentThreshold: errorPercent,
|
||||
MaxConcurrentRequests: maxConcurrent,
|
||||
})
|
||||
|
||||
var (
|
||||
breaker = circuitbreaker.Hystrix(commandName)
|
||||
primeWith = hystrix.DefaultVolumeThreshold * 2
|
||||
shouldPass = func(n int) bool { return (float64(n) / float64(primeWith+n)) <= (float64(errorPercent-1) / 100.0) }
|
||||
openCircuitError = hystrix.ErrCircuitOpen.Error()
|
||||
)
|
||||
|
||||
// hystrix-go uses buffered channels to receive reports on request success/failure,
|
||||
// and so is basically impossible to test deterministically. We have to make sure
|
||||
// the report buffer is emptied, by injecting a sleep between each invocation.
|
||||
requestDelay := 5 * time.Millisecond
|
||||
|
||||
testFailingEndpoint(t, breaker, primeWith, shouldPass, requestDelay, openCircuitError)
|
||||
}
|
75
vendor/github.com/go-kit/kit/circuitbreaker/util_test.go
generated
vendored
Normal file
75
vendor/github.com/go-kit/kit/circuitbreaker/util_test.go
generated
vendored
Normal file
@@ -0,0 +1,75 @@
|
||||
package circuitbreaker_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/go-kit/kit/endpoint"
|
||||
)
|
||||
|
||||
func testFailingEndpoint(
|
||||
t *testing.T,
|
||||
breaker endpoint.Middleware,
|
||||
primeWith int,
|
||||
shouldPass func(int) bool,
|
||||
requestDelay time.Duration,
|
||||
openCircuitError string,
|
||||
) {
|
||||
_, file, line, _ := runtime.Caller(1)
|
||||
caller := fmt.Sprintf("%s:%d", filepath.Base(file), line)
|
||||
|
||||
// Create a mock endpoint and wrap it with the breaker.
|
||||
m := mock{}
|
||||
var e endpoint.Endpoint
|
||||
e = m.endpoint
|
||||
e = breaker(e)
|
||||
|
||||
// Prime the endpoint with successful requests.
|
||||
for i := 0; i < primeWith; i++ {
|
||||
if _, err := e(context.Background(), struct{}{}); err != nil {
|
||||
t.Fatalf("%s: during priming, got error: %v", caller, err)
|
||||
}
|
||||
time.Sleep(requestDelay)
|
||||
}
|
||||
|
||||
// Switch the endpoint to start throwing errors.
|
||||
m.err = errors.New("tragedy+disaster")
|
||||
m.through = 0
|
||||
|
||||
// The first several should be allowed through and yield our error.
|
||||
for i := 0; shouldPass(i); i++ {
|
||||
if _, err := e(context.Background(), struct{}{}); err != m.err {
|
||||
t.Fatalf("%s: want %v, have %v", caller, m.err, err)
|
||||
}
|
||||
time.Sleep(requestDelay)
|
||||
}
|
||||
through := m.through
|
||||
|
||||
// But the rest should be blocked by an open circuit.
|
||||
for i := 0; i < 10; i++ {
|
||||
if _, err := e(context.Background(), struct{}{}); err.Error() != openCircuitError {
|
||||
t.Fatalf("%s: want %q, have %q", caller, openCircuitError, err.Error())
|
||||
}
|
||||
time.Sleep(requestDelay)
|
||||
}
|
||||
|
||||
// Make sure none of those got through.
|
||||
if want, have := through, m.through; want != have {
|
||||
t.Errorf("%s: want %d, have %d", caller, want, have)
|
||||
}
|
||||
}
|
||||
|
||||
type mock struct {
|
||||
through int
|
||||
err error
|
||||
}
|
||||
|
||||
func (m *mock) endpoint(context.Context, interface{}) (interface{}, error) {
|
||||
m.through++
|
||||
return struct{}{}, m.err
|
||||
}
|
Reference in New Issue
Block a user