sony / gobreaker Goto Github PK
View Code? Open in Web Editor NEWCircuit Breaker implemented in Go
License: MIT License
Circuit Breaker implemented in Go
License: MIT License
Hello guys, our production is suffers from "too many requests" and I'm struggle to reproduce this error.
I set CB to half-open state, but I cannot reproduce that error, it goes to only to close or open state.
Can you please explain what steps I should do to get it.
Hi! I notice that this project doesn't have any tagged releases. Would you mind adding some SemVer-compatible release tags? It would really, really help those of us using dep
and similar tools.
I want to collect metrics based on Counts
struct.
Initially, I think that I can put my metrics on ReadyToTrip
but it is called only onFailure
.
Can we have a method that is called whatever the result success/failure in order to display the metrics for each Allow
?
I can propose a PR if you want.
It is stated that
// MaxRequests is the maximum number of requests allowed to pass through
// when the CircuitBreaker is half-open.
// If MaxRequests is 0, the CircuitBreaker allows only 1 request.
Considering this, I assume that the circuit breaker will perform MaxRequests
count of operations before opening? But it doesn't.
Here is a reproducible code
package main
import (
"errors"
"fmt"
"github.com/sony/gobreaker"
"time"
)
func main() {
cb := gobreaker.NewCircuitBreaker(gobreaker.Settings{
Name: "sad",
MaxRequests: 20,
Interval: time.Second * 10,
Timeout: time.Second * 1,
ReadyToTrip: func(counts gobreaker.Counts) bool {
failureRatio := float64(counts.TotalFailures) / float64(counts.Requests)
if failureRatio > 0.7 {
fmt.Printf("will trip? %+v\n", counts)
}
return counts.Requests >= 100 && failureRatio > 0.7
},
OnStateChange: func(name string, from gobreaker.State, to gobreaker.State) {
fmt.Printf("Circuit breaker %v state change from %v to %v\n", name, from, to)
},
})
for {
cb.Execute(func() (interface{}, error) {
return nil, fun()
})
}
}
func fun() error {
fmt.Println("RUNNING")
return errors.New("LMAO")
}
This prints...
RUNNING
will trip? {Requests:1 TotalSuccesses:0 TotalFailures:1 ConsecutiveSuccesses:0 ConsecutiveFailures:1}
RUNNING
will trip? {Requests:2 TotalSuccesses:0 TotalFailures:2 ConsecutiveSuccesses:0 ConsecutiveFailures:2}
RUNNING
will trip? {Requests:3 TotalSuccesses:0 TotalFailures:3 ConsecutiveSuccesses:0 ConsecutiveFailures:3}
RUNNING
will trip? {Requests:4 TotalSuccesses:0 TotalFailures:4 ConsecutiveSuccesses:0 ConsecutiveFailures:4}
RUNNING
will trip? {Requests:5 TotalSuccesses:0 TotalFailures:5 ConsecutiveSuccesses:0 ConsecutiveFailures:5}
RUNNING
will trip? {Requests:6 TotalSuccesses:0 TotalFailures:6 ConsecutiveSuccesses:0 ConsecutiveFailures:6}
RUNNING
will trip? {Requests:7 TotalSuccesses:0 TotalFailures:7 ConsecutiveSuccesses:0 ConsecutiveFailures:7}
RUNNING
will trip? {Requests:8 TotalSuccesses:0 TotalFailures:8 ConsecutiveSuccesses:0 ConsecutiveFailures:8}
RUNNING
will trip? {Requests:9 TotalSuccesses:0 TotalFailures:9 ConsecutiveSuccesses:0 ConsecutiveFailures:9}
RUNNING
will trip? {Requests:10 TotalSuccesses:0 TotalFailures:10 ConsecutiveSuccesses:0 ConsecutiveFailures:10}
RUNNING
will trip? {Requests:11 TotalSuccesses:0 TotalFailures:11 ConsecutiveSuccesses:0 ConsecutiveFailures:11}
RUNNING
will trip? {Requests:12 TotalSuccesses:0 TotalFailures:12 ConsecutiveSuccesses:0 ConsecutiveFailures:12}
RUNNING
will trip? {Requests:13 TotalSuccesses:0 TotalFailures:13 ConsecutiveSuccesses:0 ConsecutiveFailures:13}
RUNNING
will trip? {Requests:14 TotalSuccesses:0 TotalFailures:14 ConsecutiveSuccesses:0 ConsecutiveFailures:14}
RUNNING
will trip? {Requests:15 TotalSuccesses:0 TotalFailures:15 ConsecutiveSuccesses:0 ConsecutiveFailures:15}
RUNNING
will trip? {Requests:16 TotalSuccesses:0 TotalFailures:16 ConsecutiveSuccesses:0 ConsecutiveFailures:16}
RUNNING
will trip? {Requests:17 TotalSuccesses:0 TotalFailures:17 ConsecutiveSuccesses:0 ConsecutiveFailures:17}
RUNNING
will trip? {Requests:18 TotalSuccesses:0 TotalFailures:18 ConsecutiveSuccesses:0 ConsecutiveFailures:18}
RUNNING
will trip? {Requests:19 TotalSuccesses:0 TotalFailures:19 ConsecutiveSuccesses:0 ConsecutiveFailures:19}
RUNNING
will trip? {Requests:20 TotalSuccesses:0 TotalFailures:20 ConsecutiveSuccesses:0 ConsecutiveFailures:20}
RUNNING
will trip? {Requests:21 TotalSuccesses:0 TotalFailures:21 ConsecutiveSuccesses:0 ConsecutiveFailures:21}
RUNNING
will trip? {Requests:22 TotalSuccesses:0 TotalFailures:22 ConsecutiveSuccesses:0 ConsecutiveFailures:22}
RUNNING
will trip? {Requests:23 TotalSuccesses:0 TotalFailures:23 ConsecutiveSuccesses:0 ConsecutiveFailures:23}
RUNNING
will trip? {Requests:24 TotalSuccesses:0 TotalFailures:24 ConsecutiveSuccesses:0 ConsecutiveFailures:24}
RUNNING
will trip? {Requests:25 TotalSuccesses:0 TotalFailures:25 ConsecutiveSuccesses:0 ConsecutiveFailures:25}
RUNNING
will trip? {Requests:26 TotalSuccesses:0 TotalFailures:26 ConsecutiveSuccesses:0 ConsecutiveFailures:26}
RUNNING
will trip? {Requests:27 TotalSuccesses:0 TotalFailures:27 ConsecutiveSuccesses:0 ConsecutiveFailures:27}
RUNNING
will trip? {Requests:28 TotalSuccesses:0 TotalFailures:28 ConsecutiveSuccesses:0 ConsecutiveFailures:28}
RUNNING
will trip? {Requests:29 TotalSuccesses:0 TotalFailures:29 ConsecutiveSuccesses:0 ConsecutiveFailures:29}
RUNNING
will trip? {Requests:30 TotalSuccesses:0 TotalFailures:30 ConsecutiveSuccesses:0 ConsecutiveFailures:30}
RUNNING
will trip? {Requests:31 TotalSuccesses:0 TotalFailures:31 ConsecutiveSuccesses:0 ConsecutiveFailures:31}
RUNNING
will trip? {Requests:32 TotalSuccesses:0 TotalFailures:32 ConsecutiveSuccesses:0 ConsecutiveFailures:32}
RUNNING
will trip? {Requests:33 TotalSuccesses:0 TotalFailures:33 ConsecutiveSuccesses:0 ConsecutiveFailures:33}
RUNNING
will trip? {Requests:34 TotalSuccesses:0 TotalFailures:34 ConsecutiveSuccesses:0 ConsecutiveFailures:34}
RUNNING
will trip? {Requests:35 TotalSuccesses:0 TotalFailures:35 ConsecutiveSuccesses:0 ConsecutiveFailures:35}
RUNNING
will trip? {Requests:36 TotalSuccesses:0 TotalFailures:36 ConsecutiveSuccesses:0 ConsecutiveFailures:36}
RUNNING
will trip? {Requests:37 TotalSuccesses:0 TotalFailures:37 ConsecutiveSuccesses:0 ConsecutiveFailures:37}
RUNNING
will trip? {Requests:38 TotalSuccesses:0 TotalFailures:38 ConsecutiveSuccesses:0 ConsecutiveFailures:38}
RUNNING
will trip? {Requests:39 TotalSuccesses:0 TotalFailures:39 ConsecutiveSuccesses:0 ConsecutiveFailures:39}
RUNNING
will trip? {Requests:40 TotalSuccesses:0 TotalFailures:40 ConsecutiveSuccesses:0 ConsecutiveFailures:40}
RUNNING
will trip? {Requests:41 TotalSuccesses:0 TotalFailures:41 ConsecutiveSuccesses:0 ConsecutiveFailures:41}
RUNNING
will trip? {Requests:42 TotalSuccesses:0 TotalFailures:42 ConsecutiveSuccesses:0 ConsecutiveFailures:42}
RUNNING
will trip? {Requests:43 TotalSuccesses:0 TotalFailures:43 ConsecutiveSuccesses:0 ConsecutiveFailures:43}
RUNNING
will trip? {Requests:44 TotalSuccesses:0 TotalFailures:44 ConsecutiveSuccesses:0 ConsecutiveFailures:44}
RUNNING
will trip? {Requests:45 TotalSuccesses:0 TotalFailures:45 ConsecutiveSuccesses:0 ConsecutiveFailures:45}
RUNNING
will trip? {Requests:46 TotalSuccesses:0 TotalFailures:46 ConsecutiveSuccesses:0 ConsecutiveFailures:46}
RUNNING
will trip? {Requests:47 TotalSuccesses:0 TotalFailures:47 ConsecutiveSuccesses:0 ConsecutiveFailures:47}
RUNNING
will trip? {Requests:48 TotalSuccesses:0 TotalFailures:48 ConsecutiveSuccesses:0 ConsecutiveFailures:48}
RUNNING
will trip? {Requests:49 TotalSuccesses:0 TotalFailures:49 ConsecutiveSuccesses:0 ConsecutiveFailures:49}
RUNNING
will trip? {Requests:50 TotalSuccesses:0 TotalFailures:50 ConsecutiveSuccesses:0 ConsecutiveFailures:50}
RUNNING
will trip? {Requests:51 TotalSuccesses:0 TotalFailures:51 ConsecutiveSuccesses:0 ConsecutiveFailures:51}
RUNNING
will trip? {Requests:52 TotalSuccesses:0 TotalFailures:52 ConsecutiveSuccesses:0 ConsecutiveFailures:52}
RUNNING
will trip? {Requests:53 TotalSuccesses:0 TotalFailures:53 ConsecutiveSuccesses:0 ConsecutiveFailures:53}
RUNNING
will trip? {Requests:54 TotalSuccesses:0 TotalFailures:54 ConsecutiveSuccesses:0 ConsecutiveFailures:54}
RUNNING
will trip? {Requests:55 TotalSuccesses:0 TotalFailures:55 ConsecutiveSuccesses:0 ConsecutiveFailures:55}
RUNNING
will trip? {Requests:56 TotalSuccesses:0 TotalFailures:56 ConsecutiveSuccesses:0 ConsecutiveFailures:56}
RUNNING
will trip? {Requests:57 TotalSuccesses:0 TotalFailures:57 ConsecutiveSuccesses:0 ConsecutiveFailures:57}
RUNNING
will trip? {Requests:58 TotalSuccesses:0 TotalFailures:58 ConsecutiveSuccesses:0 ConsecutiveFailures:58}
RUNNING
will trip? {Requests:59 TotalSuccesses:0 TotalFailures:59 ConsecutiveSuccesses:0 ConsecutiveFailures:59}
RUNNING
will trip? {Requests:60 TotalSuccesses:0 TotalFailures:60 ConsecutiveSuccesses:0 ConsecutiveFailures:60}
RUNNING
will trip? {Requests:61 TotalSuccesses:0 TotalFailures:61 ConsecutiveSuccesses:0 ConsecutiveFailures:61}
RUNNING
will trip? {Requests:62 TotalSuccesses:0 TotalFailures:62 ConsecutiveSuccesses:0 ConsecutiveFailures:62}
RUNNING
will trip? {Requests:63 TotalSuccesses:0 TotalFailures:63 ConsecutiveSuccesses:0 ConsecutiveFailures:63}
RUNNING
will trip? {Requests:64 TotalSuccesses:0 TotalFailures:64 ConsecutiveSuccesses:0 ConsecutiveFailures:64}
RUNNING
will trip? {Requests:65 TotalSuccesses:0 TotalFailures:65 ConsecutiveSuccesses:0 ConsecutiveFailures:65}
RUNNING
will trip? {Requests:66 TotalSuccesses:0 TotalFailures:66 ConsecutiveSuccesses:0 ConsecutiveFailures:66}
RUNNING
will trip? {Requests:67 TotalSuccesses:0 TotalFailures:67 ConsecutiveSuccesses:0 ConsecutiveFailures:67}
RUNNING
will trip? {Requests:68 TotalSuccesses:0 TotalFailures:68 ConsecutiveSuccesses:0 ConsecutiveFailures:68}
RUNNING
will trip? {Requests:69 TotalSuccesses:0 TotalFailures:69 ConsecutiveSuccesses:0 ConsecutiveFailures:69}
RUNNING
will trip? {Requests:70 TotalSuccesses:0 TotalFailures:70 ConsecutiveSuccesses:0 ConsecutiveFailures:70}
RUNNING
will trip? {Requests:71 TotalSuccesses:0 TotalFailures:71 ConsecutiveSuccesses:0 ConsecutiveFailures:71}
RUNNING
will trip? {Requests:72 TotalSuccesses:0 TotalFailures:72 ConsecutiveSuccesses:0 ConsecutiveFailures:72}
RUNNING
will trip? {Requests:73 TotalSuccesses:0 TotalFailures:73 ConsecutiveSuccesses:0 ConsecutiveFailures:73}
RUNNING
will trip? {Requests:74 TotalSuccesses:0 TotalFailures:74 ConsecutiveSuccesses:0 ConsecutiveFailures:74}
RUNNING
will trip? {Requests:75 TotalSuccesses:0 TotalFailures:75 ConsecutiveSuccesses:0 ConsecutiveFailures:75}
RUNNING
will trip? {Requests:76 TotalSuccesses:0 TotalFailures:76 ConsecutiveSuccesses:0 ConsecutiveFailures:76}
RUNNING
will trip? {Requests:77 TotalSuccesses:0 TotalFailures:77 ConsecutiveSuccesses:0 ConsecutiveFailures:77}
RUNNING
will trip? {Requests:78 TotalSuccesses:0 TotalFailures:78 ConsecutiveSuccesses:0 ConsecutiveFailures:78}
RUNNING
will trip? {Requests:79 TotalSuccesses:0 TotalFailures:79 ConsecutiveSuccesses:0 ConsecutiveFailures:79}
RUNNING
will trip? {Requests:80 TotalSuccesses:0 TotalFailures:80 ConsecutiveSuccesses:0 ConsecutiveFailures:80}
RUNNING
will trip? {Requests:81 TotalSuccesses:0 TotalFailures:81 ConsecutiveSuccesses:0 ConsecutiveFailures:81}
RUNNING
will trip? {Requests:82 TotalSuccesses:0 TotalFailures:82 ConsecutiveSuccesses:0 ConsecutiveFailures:82}
RUNNING
will trip? {Requests:83 TotalSuccesses:0 TotalFailures:83 ConsecutiveSuccesses:0 ConsecutiveFailures:83}
RUNNING
will trip? {Requests:84 TotalSuccesses:0 TotalFailures:84 ConsecutiveSuccesses:0 ConsecutiveFailures:84}
RUNNING
will trip? {Requests:85 TotalSuccesses:0 TotalFailures:85 ConsecutiveSuccesses:0 ConsecutiveFailures:85}
RUNNING
will trip? {Requests:86 TotalSuccesses:0 TotalFailures:86 ConsecutiveSuccesses:0 ConsecutiveFailures:86}
RUNNING
will trip? {Requests:87 TotalSuccesses:0 TotalFailures:87 ConsecutiveSuccesses:0 ConsecutiveFailures:87}
RUNNING
will trip? {Requests:88 TotalSuccesses:0 TotalFailures:88 ConsecutiveSuccesses:0 ConsecutiveFailures:88}
RUNNING
will trip? {Requests:89 TotalSuccesses:0 TotalFailures:89 ConsecutiveSuccesses:0 ConsecutiveFailures:89}
RUNNING
will trip? {Requests:90 TotalSuccesses:0 TotalFailures:90 ConsecutiveSuccesses:0 ConsecutiveFailures:90}
RUNNING
will trip? {Requests:91 TotalSuccesses:0 TotalFailures:91 ConsecutiveSuccesses:0 ConsecutiveFailures:91}
RUNNING
will trip? {Requests:92 TotalSuccesses:0 TotalFailures:92 ConsecutiveSuccesses:0 ConsecutiveFailures:92}
RUNNING
will trip? {Requests:93 TotalSuccesses:0 TotalFailures:93 ConsecutiveSuccesses:0 ConsecutiveFailures:93}
RUNNING
will trip? {Requests:94 TotalSuccesses:0 TotalFailures:94 ConsecutiveSuccesses:0 ConsecutiveFailures:94}
RUNNING
will trip? {Requests:95 TotalSuccesses:0 TotalFailures:95 ConsecutiveSuccesses:0 ConsecutiveFailures:95}
RUNNING
will trip? {Requests:96 TotalSuccesses:0 TotalFailures:96 ConsecutiveSuccesses:0 ConsecutiveFailures:96}
RUNNING
will trip? {Requests:97 TotalSuccesses:0 TotalFailures:97 ConsecutiveSuccesses:0 ConsecutiveFailures:97}
RUNNING
will trip? {Requests:98 TotalSuccesses:0 TotalFailures:98 ConsecutiveSuccesses:0 ConsecutiveFailures:98}
RUNNING
will trip? {Requests:99 TotalSuccesses:0 TotalFailures:99 ConsecutiveSuccesses:0 ConsecutiveFailures:99}
RUNNING
will trip? {Requests:100 TotalSuccesses:0 TotalFailures:100 ConsecutiveSuccesses:0 ConsecutiveFailures:100}
Circuit breaker sad state change from closed to open
Circuit breaker sad state change from open to half-open
RUNNING
Circuit breaker sad state change from half-open to open
Circuit breaker sad state change from open to half-open
RUNNING
Circuit breaker sad state change from half-open to open
^C
Why is it executing only once in half-open state?
I just give a quite look to this library. This circuit breaker is mighty simple (compared with a Hystrix-like implementation) but still powerful.
However, I have a question about the counter expiration. Hystrix uses a rolling window to store the counts. This library doesn't maintain a rolling window, instead it drops the whole counts when the time interval is passed.
There may be a problem. Considered we use 10s as an interval, and we have 10000 requests come between 1s ~ 11s, 1000 requests per each second. The last 900 requests fail in the 11s. If the rolling window is used, the error rate will be 9% (900 / 10000). However, if we are unfortunate enough that the counts are expired in 10s, the error will be 90%, since we will recount the requests from the 11s.
Maybe I am missing something. Please let me know if I am wrong.
Hi, we have a use case where we need to check the returned error, and we need to be able to see if it's returned from the CB.
Can we open a PR with an exported error?
Hi, I want to know if it is required to abort a call when we wrap a remote call e.g. http request when we reached timeout?
Thanks!
What about start a new release like v0.4.0, for the v0.3.0 is outdated... Thanks a lot
The circuit breaker pattern as per the linked docs is to allow retrying of operations that are less likely to fail. With the current code in example/ if I encounter a 404, it'll just return the 404 HTML page and moreover without any operational context hence defeating the pattern aimed for :-(
gobreaker/example/http_breaker.go
Lines 26 to 55 in e7c4cd5
There should be a way in which the example HTTP circuit breaker looks at the returned HTTP status codes. There are some for which you should not retry unless some conditions change e.g. authorization and authentication problems, not found and legal issue status codes.
At bare minimum please make the example more resilient with error checking such as
defer res.Body.Close()
if res.StatusCode/100 != 2 { // Not a 2XX successful response
... // Handle the status code in here
}
gobreaker/example/http_breaker.go
Line 54 in 3cb67c7
What is the way to collect metrics for monitoring?
It would be good to get more information about the statistic of circuit breaker than just status: open, half-open and closed.
Count contains enough information about CB condition.
type Counts struct {
Requests uint32
TotalSuccesses uint32
TotalFailures uint32
ConsecutiveSuccesses uint32
ConsecutiveFailures uint32
}
Hi,
Thanks a lot for your library, it's really helpful!
When I check the release, the latest is 0.4.1, which was published in May 2019, but the latest merge was in Jan 2021, I can use go mod to get the latest commit change, however, when we request 3rd party library approval from my company, maybe it would not be approved, so may I request a new release with tag 0.4.2? Really appreciate it!
Hi,
Thanks a lot for your library, it's simple, yet powerful! :)
Could you please clarify one confusion I have about ErrTooManyRequests error? I don't quite understand from the code when this error could happen.
I see the if state == StateHalfOpen && cb.counts.Requests >= cb.maxRequests
condition in the beforeRequest()
method but from the rest of the code it doesn't look like it could ever be met. This is because we either get enough consecutive requests to trip circuit to close with this condition if cb.counts.ConsecutiveSuccesses >= cb.maxRequests { cb.setState(StateClosed, now) }
or we go back to open state because of a single failure in onFailure()
. Or did I misunderstand something?
We would like to use circuit breaker pattern while integrating with 3rd party API's, however we want to isolate failures at integration + customer level.
For example, example.com/test is one integration can be used by customer 1 and anotherexample.com/test is another integration used by customer 2.
Let's say, when example.com/test is down and circuit trips after threshold, we do not want to affect customer 2 and others except customer of that particular integration which is down, is this possible?
I guess challenge is we upfront do not know how many integrations will be needed so we need some dynamic way to define circuit breakers per combination of integration and customer (unique id of integration might be sufficient)
Hi, I'd like to have the possibility to check if a request can pass through and setting the outcome in separate steps, outside the Execute()
method. This would be possible if the breaker had the following additional methods:
Allow() bool
: would tell if the breaker is closed, or, in half open state, can the request pass through.Success()
: report a successful outcomeFailure()
: report a failed outcomeAllow()
would be basically a visible wrapper around beforeRequest()
, while Failure()
and Success()
around afterRequest()
.
This would enable using the breaker in an asynchronous way, where the check for passing and reporting the outcome are not in a single control flow.
I'd be happy to make a pull request.
i want to use gobreaker in my project, i have chained api that looks like this:
request -> api gw -> oauth -> svc1 -> svc2 -> response
oauth, svc1 can work on multiple hosts and if one fails another can work.
doe i need to create different instances of breaker for such thing? or how to deal with such cases?
When i looked into the code I was wondering if this package would be aware of go routines.
When it would be used in http handlers to handle calls of remote services , which is often the case in my implementation . The following test shows up that it is not aware of go routines even if there is a testcase in the package tests that tries to run them in parallel.
~/Desktop/Dev/go/sony/gobreaker:$ go test -race
==================
WARNING: DATA RACE
Read at 0x00c0001160d0 by goroutine 11:
runtime.convT2Enoptr()
/usr/local/go/src/runtime/iface.go:379 +0x0
github.com/sony/gobreaker.TestCustomCircuitBreaker()
/Users/rl/Desktop/Dev/go/sony/gobreaker/gobreaker_test.go:260 +0x11db
testing.tRunner()
/usr/local/go/src/testing/testing.go:909 +0x199
Previous write at 0x00c0001160d0 by goroutine 12:
github.com/sony/gobreaker.(*CircuitBreaker).beforeRequest()
/Users/rl/Desktop/Dev/go/sony/gobreaker/gobreaker.go:56 +0x191
github.com/sony/gobreaker.(*CircuitBreaker).Execute()
/Users/rl/Desktop/Dev/go/sony/gobreaker/gobreaker.go:204 +0x63
github.com/sony/gobreaker.succeedLater.func1()
/Users/rl/Desktop/Dev/go/sony/gobreaker/gobreaker_test.go:38 +0x69
Goroutine 11 (running) created at:
testing.(*T).Run()
/usr/local/go/src/testing/testing.go:960 +0x651
testing.runTests.func1()
/usr/local/go/src/testing/testing.go:1202 +0xa6
testing.tRunner()
/usr/local/go/src/testing/testing.go:909 +0x199
testing.runTests()
/usr/local/go/src/testing/testing.go:1200 +0x521
testing.(*M).Run()
/usr/local/go/src/testing/testing.go:1117 +0x2ff
main.main()
_testmain.go:58 +0x223
Goroutine 12 (running) created at:
github.com/sony/gobreaker.succeedLater()
/Users/rl/Desktop/Dev/go/sony/gobreaker/gobreaker_test.go:37 +0x82
github.com/sony/gobreaker.TestCustomCircuitBreaker()
/Users/rl/Desktop/Dev/go/sony/gobreaker/gobreaker_test.go:258 +0x113a
testing.tRunner()
/usr/local/go/src/testing/testing.go:909 +0x199
==================
--- FAIL: TestCustomCircuitBreaker (0.10s)
testing.go:853: race detected during execution of test
FAIL
exit status 1
FAIL github.com/sony/gobreaker 2.213s
What do you think about such a situation? Is it worth to invest in a PR to make it aware of go routines and in addition to that moving from the expensive sync.Mutex handling towards go channles so that always only one go routine is maintaining the counters and state?
The go.mod file is set to work only with go 1.12
. When building with go 1.11
I get errors around which version of Go is required. Is go 1.12
required? Can this limitation be removed from the go.mod?
When the OnStateChange method is trigered, I want to know the breaker counts, so i call breaker.Counts(), but I get a deadlock
The code is :
OnStateChange: func(name string, from gobreaker.State, to gobreaker.State) {
// NOTICE:do not call breaker.Counts() in this method , it will cause a deadlock !!!
counts := breaker.Counts()
logger.Infof("key: %s, breaker state has change, from %s to %s , the data --> %v", breaker.Name(), from.String(), to.String(), counts)
}
What method should I call when I want to know the counts number in OnStateChange method ?
Is any benchmarking available for this circuit breaker? Will it help to use sync/atomic to keep the counts instead of using mutex for locking?
Or are there some race conditions not satisfied by sync/atomic that I am overlooking.
In the current implementation of the CircuitBreaker
library, the logic for determining whether the circuit should transition from StateHalfOpen
to StateClosed
is directly embedded within the onSuccess
method. Specifically, the condition cb.counts.ConsecutiveSuccesses >= cb.maxRequests
is checked to decide if the circuit should close.
The current approach tightly couples the condition with the onSuccess
method, making the code less modular and harder to maintain. It might be helpful to adjust or extend the logic for transitioning states.
To improve code modularity and maintainability, I propose encapsulating the condition cb.counts.ConsecutiveSuccesses >= cb.maxRequests
into a dedicated method, such as shouldCloseCircuit()
. This change would make the onSuccess
method cleaner and the success condition easier to manage and modify.
Here's how the refactored onSuccess
method would look:
func (cb *CircuitBreaker) onSuccess(state State, now time.Time) {
switch state {
case StateClosed:
cb.counts.onSuccess()
case StateHalfOpen:
cb.counts.onSuccess()
if cb.shouldCloseCircuit(cb.counts) {
cb.setState(StateClosed, now)
}
}
}
I'll be okay to send a pull request.
Do I need to use a mutex when calling cb.Execute from multiple goroutines?
as it seems, counts won't be calculated correctly and need to be synchronized
Go modules landed a few versions ago. Could you tag the a new release as v0.5.0
? Go expects tag names to have a v
prefix. Thanks!
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.