circuitbreaker: github.com/rubyist/circuitbreaker Index | Examples | Files

package circuit

import "github.com/rubyist/circuitbreaker"

Package circuit implements the Circuit Breaker pattern. It will wrap a function call (typically one which uses remote services) and monitors for failures and/or time outs. When a threshold of failures or time outs has been reached, future calls to the function will not run. During this state, the breaker will periodically allow the function to run and, if it is successful, will start running the function again.

Circuit includes three types of circuit breakers:

A Threshold Breaker will trip when the failure count reaches a given threshold. It does not matter how long it takes to reach the threshold and the failures do not need to be consecutive.

A Consecutive Breaker will trip when the consecutive failure count reaches a given threshold. It does not matter how long it takes to reach the threshold, but the failures do need to be consecutive.

When wrapping blocks of code with a Breaker's Call() function, a time out can be specified. If the time out is reached, the breaker's Fail() function will be called.

Other types of circuit breakers can be easily built by creating a Breaker and adding a custom TripFunc. A TripFunc is called when a Breaker Fail()s and receives the breaker as an argument. It then returns true or false to indicate whether the breaker should trip.

The package also provides a wrapper around an http.Client that wraps all of the http.Client functions with a Breaker.

Index

Examples

Package Files

circuitbreaker.go client.go panel.go window.go

Variables

var (
    ErrBreakerOpen    = errors.New("breaker open")
    ErrBreakerTimeout = errors.New("breaker time out")
)

Error codes returned by Call

var (
    // DefaultWindowTime is the default time the window covers, 10 seconds.
    DefaultWindowTime = time.Millisecond * 10000

    // DefaultWindowBuckets is the default number of buckets the window holds, 10.
    DefaultWindowBuckets = 10
)

type Breaker Uses

type Breaker struct {
    // BackOff is the backoff policy that is used when determining if the breaker should
    // attempt to retry. A breaker created with NewBreaker will use an exponential backoff
    // policy by default.
    BackOff backoff.BackOff

    // ShouldTrip is a TripFunc that determines whether a Fail() call should trip the breaker.
    // A breaker created with NewBreaker will not have a ShouldTrip by default, and thus will
    // never automatically trip.
    ShouldTrip TripFunc

    // Clock is used for controlling time in tests.
    Clock clock.Clock
    // contains filtered or unexported fields
}

Breaker is the base of a circuit breaker. It maintains failure and success counters as well as the event subscribers.

Code:

// This example demonstrates the BreakerTripped and BreakerReset callbacks. These are
// available on all breaker types.
breaker := NewThresholdBreaker(1)
events := breaker.Subscribe()

go func() {
    for {
        e := <-events
        switch e {
        case BreakerTripped:
            log.Println("breaker tripped")
        case BreakerReset:
            log.Println("breaker reset")
        case BreakerFail:
            log.Println("breaker fail")
        case BreakerReady:
            log.Println("breaker ready")
        }
    }
}()

breaker.Fail()
breaker.Reset()

func NewBreaker Uses

func NewBreaker() *Breaker

NewBreaker creates a base breaker with an exponential backoff and no TripFunc

func NewBreakerWithOptions Uses

func NewBreakerWithOptions(options *Options) *Breaker

NewBreakerWithOptions creates a base breaker with a specified backoff, clock and TripFunc

func NewConsecutiveBreaker Uses

func NewConsecutiveBreaker(threshold int64) *Breaker

NewConsecutiveBreaker creates a Breaker with a ConsecutiveTripFunc.

Code:

// This example sets up a FrequencyBreaker that will trip if remoteCall returns
// an error 10 times in a row within a period of 2 minutes.
breaker := NewConsecutiveBreaker(10)
err := breaker.Call(remoteCall, 0)
if err != nil {
    log.Fatal(err)
}

func NewRateBreaker Uses

func NewRateBreaker(rate float64, minSamples int64) *Breaker

NewRateBreaker creates a Breaker with a RateTripFunc.

func NewThresholdBreaker Uses

func NewThresholdBreaker(threshold int64) *Breaker

NewThresholdBreaker creates a Breaker with a ThresholdTripFunc.

Code:

// This example sets up a ThresholdBreaker that will trip if remoteCall returns
// an error 10 times in a row. The error returned by Call() will be the error
// returned by remoteCall, unless the breaker has been tripped, in which case
// it will return ErrBreakerOpen.
breaker := NewThresholdBreaker(10)
err := breaker.Call(remoteCall, 0)
if err != nil {
    log.Fatal(err)
}

Code:

// This example demonstrates the manual use of a ThresholdBreaker. The breaker
// will trip when Fail is called 10 times in a row.
breaker := NewThresholdBreaker(10)
if breaker.Ready() {
    err := remoteCall()
    if err != nil {
        breaker.Fail()
        log.Fatal(err)
    } else {
        breaker.Success()
    }
}

Code:

// This example sets up a ThresholdBreaker that will trip if remoteCall
// returns an error OR takes longer than one second 10 times in a row. The
// error returned by Call() will be the error returned by remoteCall with
// two exceptions: if remoteCall takes longer than one second the return
// value will be ErrBreakerTimeout, if the breaker has been tripped the
// return value will be ErrBreakerOpen.
breaker := NewThresholdBreaker(10)
err := breaker.Call(remoteCall, time.Second)
if err != nil {
    log.Fatal(err)
}

func (*Breaker) AddListener Uses

func (cb *Breaker) AddListener(listener chan ListenerEvent)

AddListener adds a channel of ListenerEvents on behalf of a listener. The listener channel must be buffered.

func (*Breaker) Break Uses

func (cb *Breaker) Break()

Break trips the circuit breaker and prevents it from auto resetting. Use this when manual control over the circuit breaker state is needed.

func (*Breaker) Call Uses

func (cb *Breaker) Call(circuit func() error, timeout time.Duration) error

Call wraps a function the Breaker will protect. A failure is recorded whenever the function returns an error. If the called function takes longer than timeout to run, a failure will be recorded.

func (*Breaker) CallContext Uses

func (cb *Breaker) CallContext(ctx context.Context, circuit func() error, timeout time.Duration) error

CallContext is same as Call but if the ctx is canceled after the circuit returned an error, the error will not be marked as a failure because the call was canceled intentionally.

func (*Breaker) ConsecFailures Uses

func (cb *Breaker) ConsecFailures() int64

ConsecFailures returns the number of consecutive failures that have occured.

func (*Breaker) ErrorRate Uses

func (cb *Breaker) ErrorRate() float64

ErrorRate returns the current error rate of the Breaker, expressed as a floating point number (e.g. 0.9 for 90%), since the last time the breaker was Reset.

func (*Breaker) Fail Uses

func (cb *Breaker) Fail()

Fail is used to indicate a failure condition the Breaker should record. It will increment the failure counters and store the time of the last failure. If the breaker has a TripFunc it will be called, tripping the breaker if necessary.

func (*Breaker) Failures Uses

func (cb *Breaker) Failures() int64

Failures returns the number of failures for this circuit breaker.

func (*Breaker) Ready Uses

func (cb *Breaker) Ready() bool

Ready will return true if the circuit breaker is ready to call the function. It will be ready if the breaker is in a reset state, or if it is time to retry the call for auto resetting.

func (*Breaker) RemoveListener Uses

func (cb *Breaker) RemoveListener(listener chan ListenerEvent) bool

RemoveListener removes a channel previously added via AddListener. Once removed, the channel will no longer receive ListenerEvents. Returns true if the listener was found and removed.

func (*Breaker) Reset Uses

func (cb *Breaker) Reset()

Reset will reset the circuit breaker. After Reset() is called, Tripped() will return false.

func (*Breaker) ResetCounters Uses

func (cb *Breaker) ResetCounters()

ResetCounters will reset only the failures, consecFailures, and success counters

func (*Breaker) Subscribe Uses

func (cb *Breaker) Subscribe() <-chan BreakerEvent

Subscribe returns a channel of BreakerEvents. Whenever the breaker changes state, the state will be sent over the channel. See BreakerEvent for the types of events.

func (*Breaker) Success Uses

func (cb *Breaker) Success()

Success is used to indicate a success condition the Breaker should record. If the success was triggered by a retry attempt, the breaker will be Reset().

func (*Breaker) Successes Uses

func (cb *Breaker) Successes() int64

Successes returns the number of successes for this circuit breaker.

func (*Breaker) Trip Uses

func (cb *Breaker) Trip()

Trip will trip the circuit breaker. After Trip() is called, Tripped() will return true.

func (*Breaker) Tripped Uses

func (cb *Breaker) Tripped() bool

Tripped returns true if the circuit breaker is tripped, false if it is reset.

type BreakerEvent Uses

type BreakerEvent int

BreakerEvent indicates the type of event received over an event channel

const (
    // BreakerTripped is sent when a breaker trips
    BreakerTripped BreakerEvent = iota

    // BreakerReset is sent when a breaker resets
    BreakerReset BreakerEvent = iota

    // BreakerFail is sent when Fail() is called
    BreakerFail BreakerEvent = iota

    // BreakerReady is sent when the breaker enters the half open state and is ready to retry
    BreakerReady BreakerEvent = iota
)

type HTTPClient Uses

type HTTPClient struct {
    Client         *http.Client
    BreakerTripped func()
    BreakerReset   func()
    BreakerLookup  func(*HTTPClient, interface{}) *Breaker
    Panel          *Panel
    // contains filtered or unexported fields
}

HTTPClient is a wrapper around http.Client that provides circuit breaker capabilities.

By default, the client will use its defaultBreaker. A BreakerLookup function may be provided to allow different breakers to be used based on the circumstance. See the implementation of NewHostBasedHTTPClient for an example of this.

Code:

// This example sets up an HTTP client wrapped in a ThresholdBreaker. The
// breaker will trip with the same behavior as ThresholdBreaker.
client := NewHTTPClient(time.Second*5, 10, nil)

resp, err := client.Get("http://example.com/resource.json")
if err != nil {
    log.Fatal(err)
}
resource, err := ioutil.ReadAll(resp.Body)
resp.Body.Close()
if err != nil {
    log.Fatal(err)
}
fmt.Printf("%s", resource)

func NewHTTPClient Uses

func NewHTTPClient(timeout time.Duration, threshold int64, client *http.Client) *HTTPClient

NewHTTPClient provides a circuit breaker wrapper around http.Client. It wraps all of the regular http.Client functions. Specifying 0 for timeout will give a breaker that does not check for time outs.

func NewHTTPClientWithBreaker Uses

func NewHTTPClientWithBreaker(breaker *Breaker, timeout time.Duration, client *http.Client) *HTTPClient

NewHTTPClientWithBreaker provides a circuit breaker wrapper around http.Client. It wraps all of the regular http.Client functions using the provided Breaker.

func NewHostBasedHTTPClient Uses

func NewHostBasedHTTPClient(timeout time.Duration, threshold int64, client *http.Client) *HTTPClient

NewHostBasedHTTPClient provides a circuit breaker wrapper around http.Client. This client will use one circuit breaker per host parsed from the request URL. This allows you to use a single HTTPClient for multiple hosts with one host's breaker not affecting the other hosts.

func (*HTTPClient) Do Uses

func (c *HTTPClient) Do(req *http.Request) (*http.Response, error)

Do wraps http.Client Do()

func (*HTTPClient) Get Uses

func (c *HTTPClient) Get(url string) (*http.Response, error)

Get wraps http.Client Get()

func (*HTTPClient) Head Uses

func (c *HTTPClient) Head(url string) (*http.Response, error)

Head wraps http.Client Head()

func (*HTTPClient) Post Uses

func (c *HTTPClient) Post(url string, bodyType string, body io.Reader) (*http.Response, error)

Post wraps http.Client Post()

func (*HTTPClient) PostForm Uses

func (c *HTTPClient) PostForm(url string, data url.Values) (*http.Response, error)

PostForm wraps http.Client PostForm()

type ListenerEvent Uses

type ListenerEvent struct {
    CB    *Breaker
    Event BreakerEvent
}

ListenerEvent includes a reference to the circuit breaker and the event.

type Options Uses

type Options struct {
    BackOff       backoff.BackOff
    Clock         clock.Clock
    ShouldTrip    TripFunc
    WindowTime    time.Duration
    WindowBuckets int
}

Options holds breaker configuration options.

type Panel Uses

type Panel struct {
    Statter      Statter
    StatsPrefixf string

    Circuits map[string]*Breaker
    // contains filtered or unexported fields
}

Panel tracks a group of circuit breakers by name.

Code:

// This example demonstrates using a Panel to aggregate and manage circuit breakers.
breaker1 := NewThresholdBreaker(10)
breaker2 := NewRateBreaker(0.95, 100)

panel := NewPanel()
panel.Add("breaker1", breaker1)
panel.Add("breaker2", breaker2)

// Elsewhere in the code ...
b1, _ := panel.Get("breaker1")
b1.Call(func() error {
    // Do some work
    return nil
}, 0)

b2, _ := panel.Get("breaker2")
b2.Call(func() error {
    // Do some work
    return nil
}, 0)

Code:

// This example demonstrates how to push circuit breaker stats to statsd via a Panel.
// This example uses g2s. Anything conforming to the Statter interface can be used.
s, err := g2s.Dial("udp", "statsd-server:8125")
if err != nil {
    log.Fatal(err)
}

breaker := NewThresholdBreaker(10)
panel := NewPanel()
panel.Statter = s
panel.StatsPrefixf = "sys.production.%s"
panel.Add("x", breaker)

breaker.Trip()  // sys.production.circuit.x.tripped
breaker.Reset() // sys.production.circuit.x.reset, sys.production.circuit.x.trip-time
breaker.Fail()  // sys.production.circuit.x.fail
breaker.Ready() // sys.production.circuit.x.ready (if it's tripped and ready to retry)

func NewPanel Uses

func NewPanel() *Panel

NewPanel creates a new Panel

func (*Panel) Add Uses

func (p *Panel) Add(name string, cb *Breaker)

Add sets the name as a reference to the given circuit breaker.

func (*Panel) Get Uses

func (p *Panel) Get(name string) (*Breaker, bool)

Get retrieves a circuit breaker by name. If no circuit breaker exists, it returns the NoOp one and sets ok to false.

func (*Panel) Subscribe Uses

func (p *Panel) Subscribe() <-chan PanelEvent

Subscribe returns a channel of PanelEvents. Whenever a breaker changes state, the PanelEvent will be sent over the channel. See BreakerEvent for the types of events.

type PanelEvent Uses

type PanelEvent struct {
    Name  string
    Event BreakerEvent
}

PanelEvent wraps a BreakerEvent and provides the string name of the breaker

type Statter Uses

type Statter interface {
    Counter(sampleRate float32, bucket string, n ...int)
    Timing(sampleRate float32, bucket string, d ...time.Duration)
    Gauge(sampleRate float32, bucket string, value ...string)
}

Statter interface provides a way to gather statistics from breakers

type TripFunc Uses

type TripFunc func(*Breaker) bool

TripFunc is a function called by a Breaker's Fail() function and determines whether the breaker should trip. It will receive the Breaker as an argument and returns a boolean. By default, a Breaker has no TripFunc.

func ConsecutiveTripFunc Uses

func ConsecutiveTripFunc(threshold int64) TripFunc

ConsecutiveTripFunc returns a TripFunc that trips whenever the consecutive failure count meets the threshold.

func RateTripFunc Uses

func RateTripFunc(rate float64, minSamples int64) TripFunc

RateTripFunc returns a TripFunc that trips whenever the error rate hits the threshold. The error rate is calculated as such: f = number of failures s = number of successes e = f / (f + s) The error rate is calculated over a sliding window of 10 seconds (by default) This TripFunc will not trip until there have been at least minSamples events.

func ThresholdTripFunc Uses

func ThresholdTripFunc(threshold int64) TripFunc

ThresholdTripFunc returns a TripFunc with that trips whenever the failure count meets the threshold.

Package circuit imports 12 packages (graph) and is imported by 41 packages. Updated 2018-03-13. Refresh now. Tools for package owners.