diff --git a/go.mod b/go.mod index 24bdc41341c7d..b9ffb238ad501 100644 --- a/go.mod +++ b/go.mod @@ -90,7 +90,7 @@ require ( github.com/segmentio/fasthash v1.0.3 github.com/shurcooL/httpfs v0.0.0-20230704072500-f1e31cf0ba5c github.com/shurcooL/vfsgen v0.0.0-20200824052919-0d455de96546 - github.com/sony/gobreaker v0.5.0 + github.com/sony/gobreaker/v2 v2.0.0 github.com/spf13/afero v1.11.0 github.com/stretchr/testify v1.9.0 github.com/uber/jaeger-client-go v2.30.0+incompatible diff --git a/go.sum b/go.sum index ea298e1198a7e..edeecd70c1b65 100644 --- a/go.sum +++ b/go.sum @@ -2540,6 +2540,8 @@ github.com/soniah/gosnmp v1.25.0/go.mod h1:8YvfZxH388NIIw2A+X5z2Oh97VcNhtmxDLt5Q github.com/sony/gobreaker v0.4.1/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJOjmxWY= github.com/sony/gobreaker v0.5.0 h1:dRCvqm0P490vZPmy7ppEk2qCnCieBooFJ+YoXGYB+yg= github.com/sony/gobreaker v0.5.0/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJOjmxWY= +github.com/sony/gobreaker/v2 v2.0.0 h1:23AaR4JQ65y4rz8JWMzgXw2gKOykZ/qfqYunll4OwJ4= +github.com/sony/gobreaker/v2 v2.0.0/go.mod h1:8JnRUz80DJ1/ne8M8v7nmTs2713i58nIt4s7XcGe/DI= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI= github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= diff --git a/pkg/storage/chunk/cache/memcached_client.go b/pkg/storage/chunk/cache/memcached_client.go index ffdc817b68b42..afd976babf365 100644 --- a/pkg/storage/chunk/cache/memcached_client.go +++ b/pkg/storage/chunk/cache/memcached_client.go @@ -19,7 +19,7 @@ import ( "github.com/pkg/errors" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promauto" - "github.com/sony/gobreaker" + "github.com/sony/gobreaker/v2" "github.com/grafana/loki/v3/pkg/util/constants" "github.com/grafana/loki/v3/pkg/util/jumphash" @@ -50,7 +50,7 @@ type memcachedClient struct { addresses []string provider *dns.Provider - cbs map[ /*address*/ string]*gobreaker.CircuitBreaker + cbs map[string]*gobreaker.CircuitBreaker[interface{}] cbFailures uint cbTimeout time.Duration cbInterval time.Duration @@ -152,7 +152,7 @@ func NewMemcachedClient(cfg MemcachedClientConfig, name string, r prometheus.Reg service: cfg.Service, logger: logger, provider: dns.NewProvider(logger, dnsProviderRegisterer, dns.GolangResolverType), - cbs: make(map[string]*gobreaker.CircuitBreaker), + cbs: make(map[string]*gobreaker.CircuitBreaker[interface{}]), cbFailures: cfg.CBFailures, cbInterval: cfg.CBInterval, cbTimeout: cfg.CBTimeout, @@ -201,7 +201,7 @@ func (c *memcachedClient) dialViaCircuitBreaker(network, address string, timeout c.Lock() cb := c.cbs[address] if cb == nil { - cb = gobreaker.NewCircuitBreaker(gobreaker.Settings{ + cb = gobreaker.NewCircuitBreaker[interface{}](gobreaker.Settings{ Name: c.name + ":" + address, Interval: c.cbInterval, Timeout: c.cbTimeout, @@ -295,7 +295,7 @@ func (c *memcachedClient) updateMemcacheServers() error { // Copy across circuit-breakers for current set of addresses, thus // leaving behind any for servers we won't talk to again c.Lock() - newCBs := make(map[string]*gobreaker.CircuitBreaker, len(servers)) + newCBs := make(map[string]*gobreaker.CircuitBreaker[interface{}], len(servers)) for _, address := range servers { if cb, exists := c.cbs[address]; exists { newCBs[address] = cb diff --git a/vendor/github.com/sony/gobreaker/README.md b/vendor/github.com/sony/gobreaker/README.md deleted file mode 100644 index bbc23769d6e90..0000000000000 --- a/vendor/github.com/sony/gobreaker/README.md +++ /dev/null @@ -1,132 +0,0 @@ -gobreaker -========= - -[![GoDoc](https://godoc.org/github.com/sony/gobreaker?status.svg)](http://godoc.org/github.com/sony/gobreaker) - -[gobreaker][repo-url] implements the [Circuit Breaker pattern](https://msdn.microsoft.com/en-us/library/dn589784.aspx) in Go. - -Installation ------------- - -``` -go get github.com/sony/gobreaker -``` - -Usage ------ - -The struct `CircuitBreaker` is a state machine to prevent sending requests that are likely to fail. -The function `NewCircuitBreaker` creates a new `CircuitBreaker`. - -```go -func NewCircuitBreaker(st Settings) *CircuitBreaker -``` - -You can configure `CircuitBreaker` by the struct `Settings`: - -```go -type Settings struct { - Name string - MaxRequests uint32 - Interval time.Duration - Timeout time.Duration - ReadyToTrip func(counts Counts) bool - OnStateChange func(name string, from State, to State) - IsSuccessful func(err error) bool -} -``` - -- `Name` is the name of the `CircuitBreaker`. - -- `MaxRequests` is the maximum number of requests allowed to pass through - when the `CircuitBreaker` is half-open. - If `MaxRequests` is 0, `CircuitBreaker` allows only 1 request. - -- `Interval` is the cyclic period of the closed state - for `CircuitBreaker` to clear the internal `Counts`, described later in this section. - If `Interval` is 0, `CircuitBreaker` doesn't clear the internal `Counts` during the closed state. - -- `Timeout` is the period of the open state, - after which the state of `CircuitBreaker` becomes half-open. - If `Timeout` is 0, the timeout value of `CircuitBreaker` is set to 60 seconds. - -- `ReadyToTrip` is called with a copy of `Counts` whenever a request fails in the closed state. - If `ReadyToTrip` returns true, `CircuitBreaker` will be placed into the open state. - If `ReadyToTrip` is `nil`, default `ReadyToTrip` is used. - Default `ReadyToTrip` returns true when the number of consecutive failures is more than 5. - -- `OnStateChange` is called whenever the state of `CircuitBreaker` changes. - -- `IsSuccessful` is called with the error returned from a request. - If `IsSuccessful` returns true, the error is counted as a success. - Otherwise the error is counted as a failure. - If `IsSuccessful` is nil, default `IsSuccessful` is used, which returns false for all non-nil errors. - -The struct `Counts` holds the numbers of requests and their successes/failures: - -```go -type Counts struct { - Requests uint32 - TotalSuccesses uint32 - TotalFailures uint32 - ConsecutiveSuccesses uint32 - ConsecutiveFailures uint32 -} -``` - -`CircuitBreaker` clears the internal `Counts` either -on the change of the state or at the closed-state intervals. -`Counts` ignores the results of the requests sent before clearing. - -`CircuitBreaker` can wrap any function to send a request: - -```go -func (cb *CircuitBreaker) Execute(req func() (interface{}, error)) (interface{}, error) -``` - -The method `Execute` runs the given request if `CircuitBreaker` accepts it. -`Execute` returns an error instantly if `CircuitBreaker` rejects the request. -Otherwise, `Execute` returns the result of the request. -If a panic occurs in the request, `CircuitBreaker` handles it as an error -and causes the same panic again. - -Example -------- - -```go -var cb *breaker.CircuitBreaker - -func Get(url string) ([]byte, error) { - body, err := cb.Execute(func() (interface{}, error) { - resp, err := http.Get(url) - if err != nil { - return nil, err - } - - defer resp.Body.Close() - body, err := ioutil.ReadAll(resp.Body) - if err != nil { - return nil, err - } - - return body, nil - }) - if err != nil { - return nil, err - } - - return body.([]byte), nil -} -``` - -See [example](https://github.com/sony/gobreaker/blob/master/example) for details. - -License -------- - -The MIT License (MIT) - -See [LICENSE](https://github.com/sony/gobreaker/blob/master/LICENSE) for details. - - -[repo-url]: https://github.com/sony/gobreaker diff --git a/vendor/github.com/sony/gobreaker/LICENSE b/vendor/github.com/sony/gobreaker/v2/LICENSE similarity index 100% rename from vendor/github.com/sony/gobreaker/LICENSE rename to vendor/github.com/sony/gobreaker/v2/LICENSE diff --git a/vendor/github.com/sony/gobreaker/gobreaker.go b/vendor/github.com/sony/gobreaker/v2/gobreaker.go similarity index 86% rename from vendor/github.com/sony/gobreaker/gobreaker.go rename to vendor/github.com/sony/gobreaker/v2/gobreaker.go index 7503a278b670d..c0382d1544a1d 100644 --- a/vendor/github.com/sony/gobreaker/gobreaker.go +++ b/vendor/github.com/sony/gobreaker/v2/gobreaker.go @@ -114,7 +114,7 @@ type Settings struct { } // CircuitBreaker is a state machine to prevent sending requests that are likely to fail. -type CircuitBreaker struct { +type CircuitBreaker[T any] struct { name string maxRequests uint32 interval time.Duration @@ -133,13 +133,13 @@ type CircuitBreaker struct { // TwoStepCircuitBreaker is like CircuitBreaker but instead of surrounding a function // with the breaker functionality, it only checks whether a request can proceed and // expects the caller to report the outcome in a separate step using a callback. -type TwoStepCircuitBreaker struct { - cb *CircuitBreaker +type TwoStepCircuitBreaker[T any] struct { + cb *CircuitBreaker[T] } // NewCircuitBreaker returns a new CircuitBreaker configured with the given Settings. -func NewCircuitBreaker(st Settings) *CircuitBreaker { - cb := new(CircuitBreaker) +func NewCircuitBreaker[T any](st Settings) *CircuitBreaker[T] { + cb := new(CircuitBreaker[T]) cb.name = st.Name cb.onStateChange = st.OnStateChange @@ -180,9 +180,9 @@ func NewCircuitBreaker(st Settings) *CircuitBreaker { } // NewTwoStepCircuitBreaker returns a new TwoStepCircuitBreaker configured with the given Settings. -func NewTwoStepCircuitBreaker(st Settings) *TwoStepCircuitBreaker { - return &TwoStepCircuitBreaker{ - cb: NewCircuitBreaker(st), +func NewTwoStepCircuitBreaker[T any](st Settings) *TwoStepCircuitBreaker[T] { + return &TwoStepCircuitBreaker[T]{ + cb: NewCircuitBreaker[T](st), } } @@ -198,12 +198,12 @@ func defaultIsSuccessful(err error) bool { } // Name returns the name of the CircuitBreaker. -func (cb *CircuitBreaker) Name() string { +func (cb *CircuitBreaker[T]) Name() string { return cb.name } // State returns the current state of the CircuitBreaker. -func (cb *CircuitBreaker) State() State { +func (cb *CircuitBreaker[T]) State() State { cb.mutex.Lock() defer cb.mutex.Unlock() @@ -213,7 +213,7 @@ func (cb *CircuitBreaker) State() State { } // Counts returns internal counters -func (cb *CircuitBreaker) Counts() Counts { +func (cb *CircuitBreaker[T]) Counts() Counts { cb.mutex.Lock() defer cb.mutex.Unlock() @@ -225,10 +225,11 @@ func (cb *CircuitBreaker) Counts() Counts { // Otherwise, Execute returns the result of the request. // If a panic occurs in the request, the CircuitBreaker handles it as an error // and causes the same panic again. -func (cb *CircuitBreaker) Execute(req func() (interface{}, error)) (interface{}, error) { +func (cb *CircuitBreaker[T]) Execute(req func() (T, error)) (T, error) { generation, err := cb.beforeRequest() if err != nil { - return nil, err + var defaultValue T + return defaultValue, err } defer func() { @@ -245,24 +246,24 @@ func (cb *CircuitBreaker) Execute(req func() (interface{}, error)) (interface{}, } // Name returns the name of the TwoStepCircuitBreaker. -func (tscb *TwoStepCircuitBreaker) Name() string { +func (tscb *TwoStepCircuitBreaker[T]) Name() string { return tscb.cb.Name() } // State returns the current state of the TwoStepCircuitBreaker. -func (tscb *TwoStepCircuitBreaker) State() State { +func (tscb *TwoStepCircuitBreaker[T]) State() State { return tscb.cb.State() } // Counts returns internal counters -func (tscb *TwoStepCircuitBreaker) Counts() Counts { +func (tscb *TwoStepCircuitBreaker[T]) Counts() Counts { return tscb.cb.Counts() } // Allow checks if a new request can proceed. It returns a callback that should be used to // register the success or failure in a separate step. If the circuit breaker doesn't allow // requests, it returns an error. -func (tscb *TwoStepCircuitBreaker) Allow() (done func(success bool), err error) { +func (tscb *TwoStepCircuitBreaker[T]) Allow() (done func(success bool), err error) { generation, err := tscb.cb.beforeRequest() if err != nil { return nil, err @@ -273,7 +274,7 @@ func (tscb *TwoStepCircuitBreaker) Allow() (done func(success bool), err error) }, nil } -func (cb *CircuitBreaker) beforeRequest() (uint64, error) { +func (cb *CircuitBreaker[T]) beforeRequest() (uint64, error) { cb.mutex.Lock() defer cb.mutex.Unlock() @@ -290,7 +291,7 @@ func (cb *CircuitBreaker) beforeRequest() (uint64, error) { return generation, nil } -func (cb *CircuitBreaker) afterRequest(before uint64, success bool) { +func (cb *CircuitBreaker[T]) afterRequest(before uint64, success bool) { cb.mutex.Lock() defer cb.mutex.Unlock() @@ -307,7 +308,7 @@ func (cb *CircuitBreaker) afterRequest(before uint64, success bool) { } } -func (cb *CircuitBreaker) onSuccess(state State, now time.Time) { +func (cb *CircuitBreaker[T]) onSuccess(state State, now time.Time) { switch state { case StateClosed: cb.counts.onSuccess() @@ -319,7 +320,7 @@ func (cb *CircuitBreaker) onSuccess(state State, now time.Time) { } } -func (cb *CircuitBreaker) onFailure(state State, now time.Time) { +func (cb *CircuitBreaker[T]) onFailure(state State, now time.Time) { switch state { case StateClosed: cb.counts.onFailure() @@ -331,7 +332,7 @@ func (cb *CircuitBreaker) onFailure(state State, now time.Time) { } } -func (cb *CircuitBreaker) currentState(now time.Time) (State, uint64) { +func (cb *CircuitBreaker[T]) currentState(now time.Time) (State, uint64) { switch cb.state { case StateClosed: if !cb.expiry.IsZero() && cb.expiry.Before(now) { @@ -345,7 +346,7 @@ func (cb *CircuitBreaker) currentState(now time.Time) (State, uint64) { return cb.state, cb.generation } -func (cb *CircuitBreaker) setState(state State, now time.Time) { +func (cb *CircuitBreaker[T]) setState(state State, now time.Time) { if cb.state == state { return } @@ -360,7 +361,7 @@ func (cb *CircuitBreaker) setState(state State, now time.Time) { } } -func (cb *CircuitBreaker) toNewGeneration(now time.Time) { +func (cb *CircuitBreaker[T]) toNewGeneration(now time.Time) { cb.generation++ cb.counts.clear() diff --git a/vendor/modules.txt b/vendor/modules.txt index 52b26a5beb8c6..966ce5cf09c08 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -1533,9 +1533,9 @@ github.com/shurcooL/vfsgen # github.com/sirupsen/logrus v1.9.3 ## explicit; go 1.13 github.com/sirupsen/logrus -# github.com/sony/gobreaker v0.5.0 -## explicit; go 1.12 -github.com/sony/gobreaker +# github.com/sony/gobreaker/v2 v2.0.0 +## explicit; go 1.21 +github.com/sony/gobreaker/v2 # github.com/spaolacci/murmur3 v1.1.0 ## explicit github.com/spaolacci/murmur3