backoff

package
v0.4.0-rc3 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 15, 2016 License: MIT, MIT Imports: 4 Imported by: 0

README

backoff

GoDoc Build Status

This is a Go port of the exponential backoff algorithm from google-http-java-client.

Exponential backoff is an algorithm that uses feedback to multiplicatively decrease the rate of some process, in order to gradually find an acceptable rate. The retries exponentially increase and stop increasing when a certain threshold is met.

Install

go get github.com/cenkalti/backoff

Example

Simple retry helper that uses exponential back-off algorithm:

operation := func() error {
    // An operation that might fail
}

err := backoff.Retry(operation, backoff.NewExponentialBackOff())
if err != nil {
    // handle error
}

// operation is successfull

Ticker example:

operation := func() error {
    // An operation that may fail
}

b := backoff.NewExponentialBackOff()
ticker := backoff.NewTicker(b)

var err error

// Ticks will continue to arrive when the previous operation is still running,
// so operations that take a while to fail could run in quick succession.
for t = range ticker.C {
    if err = operation(); err != nil {
        log.Println(err, "will retry...")
        continue
    }

    ticker.Stop()
    break
}

if err != nil {
    // Operation has failed.
}

// Operation is successfull.

Documentation

Overview

Package backoff implements backoff algorithms for retrying operations.

Also has a Retry() helper for retrying operations that may fail.

Index

Constants

View Source
const (
	DefaultInitialInterval     = 500 * time.Millisecond
	DefaultRandomizationFactor = 0.5
	DefaultMultiplier          = 1.5
	DefaultMaxInterval         = 60 * time.Second
	DefaultMaxElapsedTime      = 15 * time.Minute
)

Default values for ExponentialBackOff.

View Source
const Stop time.Duration = -1

Indicates that no more retries should be made for use in NextBackOff().

Variables

View Source
var SystemClock = systemClock{}

SystemClock implements Clock interface that uses time.Now().

Functions

func Retry

func Retry(f func() error, b BackOff) error

Retry the function f until it does not return error or BackOff stops. f is guaranteed to be run at least once. It is the caller's responsibility to reset b after Retry returns.

Retry sleeps the goroutine for the duration returned by BackOff after a failed operation returns.

Usage:

operation := func() error {
	// An operation that may fail
}

err := backoff.Retry(operation, backoff.NewExponentialBackOff())
if err != nil {
	// Operation has failed.
}

// Operation is successfull.

func RetryNotify

func RetryNotify(f func() error, b BackOff, notify func(err error, wait time.Duration)) error

RetryNotify calls notify function with the error and wait duration for each failed attempt before sleep.

Types

type BackOff

type BackOff interface {
	// Gets the duration to wait before retrying the operation or
	// backoff.Stop to indicate that no retries should be made.
	//
	// Example usage:
	//
	// 	duration := backoff.NextBackOff();
	// 	if (duration == backoff.Stop) {
	// 		// do not retry operation
	// 	} else {
	// 		// sleep for duration and retry operation
	// 	}
	//
	NextBackOff() time.Duration

	// Reset to initial state.
	Reset()
}

Back-off policy when retrying an operation.

type Clock

type Clock interface {
	Now() time.Time
}

Clock is an interface that returns current time for BackOff.

type ConstantBackOff

type ConstantBackOff struct {
	Interval time.Duration
}

func NewConstantBackOff

func NewConstantBackOff(d time.Duration) *ConstantBackOff

func (*ConstantBackOff) NextBackOff

func (b *ConstantBackOff) NextBackOff() time.Duration

func (*ConstantBackOff) Reset

func (b *ConstantBackOff) Reset()

type ExponentialBackOff

type ExponentialBackOff struct {
	InitialInterval     time.Duration
	RandomizationFactor float64
	Multiplier          float64
	MaxInterval         time.Duration
	// After MaxElapsedTime the ExponentialBackOff stops.
	// It never stops if MaxElapsedTime == 0.
	MaxElapsedTime time.Duration
	Clock          Clock
	// contains filtered or unexported fields
}

ExponentialBackOff is an implementation of BackOff that increases the back off period for each retry attempt using a randomization function that grows exponentially.

NextBackOff() is calculated using the following formula:

randomized_interval =
    retry_interval * (random value in range [1 - randomization_factor, 1 + randomization_factor])

In other words NextBackOff() will range between the randomization factor percentage below and above the retry interval. For example, using 2 seconds as the base retry interval and 0.5 as the randomization factor, the actual back off period used in the next retry attempt will be between 1 and 3 seconds.

Note: max_interval caps the retry_interval and not the randomized_interval.

If the time elapsed since an ExponentialBackOff instance is created goes past the max_elapsed_time then the method NextBackOff() starts returning backoff.Stop. The elapsed time can be reset by calling Reset().

Example: The default retry_interval is .5 seconds, default randomization_factor is 0.5, default multiplier is 1.5 and the default max_interval is 1 minute. For 10 tries the sequence will be (values in seconds) and assuming we go over the max_elapsed_time on the 10th try:

request#     retry_interval     randomized_interval

1             0.5                [0.25,   0.75]
2             0.75               [0.375,  1.125]
3             1.125              [0.562,  1.687]
4             1.687              [0.8435, 2.53]
5             2.53               [1.265,  3.795]
6             3.795              [1.897,  5.692]
7             5.692              [2.846,  8.538]
8             8.538              [4.269, 12.807]
9            12.807              [6.403, 19.210]
10           19.210              backoff.Stop

Implementation is not thread-safe.

func NewExponentialBackOff

func NewExponentialBackOff() *ExponentialBackOff

NewExponentialBackOff creates an instance of ExponentialBackOff using default values.

func (*ExponentialBackOff) GetElapsedTime

func (b *ExponentialBackOff) GetElapsedTime() time.Duration

GetElapsedTime returns the elapsed time since an ExponentialBackOff instance is created and is reset when Reset() is called.

The elapsed time is computed using time.Now().UnixNano().

func (*ExponentialBackOff) NextBackOff

func (b *ExponentialBackOff) NextBackOff() time.Duration

NextBackOff calculates the next back off interval using the formula:

randomized_interval = retry_interval +/- (randomization_factor * retry_interval)

func (*ExponentialBackOff) Reset

func (b *ExponentialBackOff) Reset()

Reset the interval back to the initial retry interval and restarts the timer.

type StopBackOff

type StopBackOff struct{}

StopBackOff is a fixed back-off policy that always returns backoff.Stop for NextBackOff(), meaning that the operation should not be retried.

func (*StopBackOff) NextBackOff

func (b *StopBackOff) NextBackOff() time.Duration

func (*StopBackOff) Reset

func (b *StopBackOff) Reset()

type Ticker

type Ticker struct {
	C <-chan time.Time
	// contains filtered or unexported fields
}

Ticker holds a channel that delivers `ticks' of a clock at times reported by a BackOff.

Ticks will continue to arrive when the previous operation is still running, so operations that take a while to fail could run in quick succession.

Usage:

operation := func() error {
	// An operation that may fail
}

b := backoff.NewExponentialBackOff()
ticker := backoff.NewTicker(b)

var err error
for _ = range ticker.C {
	if err = operation(); err != nil {
		log.Println(err, "will retry...")
		continue
	}

	ticker.Stop()
	break
}

if err != nil {
	// Operation has failed.
}

// Operation is successfull.

func NewTicker

func NewTicker(b BackOff) *Ticker

NewTicker returns a new Ticker containing a channel that will send the time at times specified by the BackOff argument. Ticker is guaranteed to tick at least once. The channel is closed when Stop method is called or BackOff stops.

func (*Ticker) Stop

func (t *Ticker) Stop()

Stop turns off a ticker. After Stop, no more ticks will be sent.

type ZeroBackOff

type ZeroBackOff struct{}

ZeroBackOff is a fixed back-off policy whose back-off time is always zero, meaning that the operation is retried immediately without waiting.

func (*ZeroBackOff) NextBackOff

func (b *ZeroBackOff) NextBackOff() time.Duration

func (*ZeroBackOff) Reset

func (b *ZeroBackOff) Reset()

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL