The Circuit Breaker pattern, can prevent an application from repeatedly trying to execute an operation that's likely to fail. Allowing it to continue without waiting for the fault to be fixed or wasting CPU cycles while it determines that the fault is long lasting. The Circuit Breaker pattern also enables an application to detect whether the fault has been resolved. If the problem appears to have been fixed, the application can try to invoke the operation.
In this package we provide you an implementation of Circuit Breaker pattern.
go get github.com/mrsoftware/circuitbreaker
consider each instance as a circuit, and it's a state matchine. you can create a circuit using NewCircuit
.
we only support redis
and memory
storage.
for code documentation you can use Go Doc.
cb := circuitbreaker.NewCircuit(circuitbreaker.WithDefaultOptions())
func Get(ctx context.Context, url string) (res []byte, err error) {
// first you have to check the circuit state.
if !cb.IsAvailable(ctx) {
return nil, circuitbreaker.ErrIsOpen // or any error you like
}
// after the proccess is done, we need to notify the circuit breaker the the result.
defer func() { cb.Done(ctx, err) }()
resp, err := http.Get(url)
if err != nil {
return nil, err
}
if resp.StatusCode != 200 {
return nil, errors.New("response status code is not 200")
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil {
return nil, err
}
return body, nil
}
cb := circuitbreaker.NewCircuit(circuitbreaker.WithDefaultOptions())
func Get(ctx context.Context, url string) (res []byte, err error) {
// no need to check the circuit breaker state and report the result to it, `Do` will do them for you.
response, err := cb.Do(ctx, func() (interface{}, error) {
resp, err := http.Get(url)
if err != nil {
return nil, err
}
if resp.StatusCode != 200 {
return nil, errors.New("response status code is not 200")
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil {
return nil, err
}
return body, nil
})
if err != nil {
return nil, err
}
return response.([]byte), nil
}
you can get circuit stat by calling Stat
method on Circuit
like below:
cb := circuitbreaker.NewCircuit(circuitbreaker.WithDefaultOptions())
stat := cb.Stat(context.Background())