retry

package
v0.1.1 Latest Latest
Warning

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

Go to latest
Published: Mar 28, 2022 License: Apache-2.0 Imports: 6 Imported by: 0

README

Retry Backoff

Inspired by line/armeria retry-backoff package, controls backoff between attempts in a single retry operation.

Supporting backoff strategies:

  • Exponential
  • Fixed
  • Jitter
  • Random

Usage

package main

import (
    "go.linecorp.com/garr/retry"
)

func main() {
	builder := retry.NewBackoffBuilder()
	if _, err := builder.Build(); err == nil {
		panic(err)
	}

	// build a fixed attempt backoff
	// remember that base backoff is mandatory
	builder = NewBackoffBuilder().BaseBackoffSpec("fixed=456")

	backoff, err := builder.Build()
	if err != nil || backoff == nil {
		panic(err)
	}
    
	for i := 0; i < 10000; i++ {
		if backoff.NextDelayMillis(i) != 456 {
			t.FailNow()
		}
	}
    
	// backoff with jitter
	builder = retry.NewBackoffBuilder().
			BaseBackoff(fixedBackoff).
			WithLimit(5).
			WithJitter(0.9).
			WithJitterBound(0.9, 1.2)
	backoff, err = builder.Build()
    
	if backoff.NextDelayMillis(6) < 0 {
		// should stop retrying
		stopRetrying()
	} else {
		panic("wrong backoff")
	}
}

Documentation

Overview

package retry contains various backoff algorithms/strategies.

Index

Constants

View Source
const (
	// DefaultDelayMillis is default delay millis.
	DefaultDelayMillis int64 = 200
	// DefaultInitialDelayMillis is default initial delay millis.
	DefaultInitialDelayMillis int64 = 200
	// DefaultMinDelayMillis is default min delay millis.
	DefaultMinDelayMillis int64 = 0
	// DefaultMaxDelayMillis is default max delay millis.
	DefaultMaxDelayMillis int64 = 10000
	// DefaultMultiplier is default multiplier.
	DefaultMultiplier float64 = 2.0
	// DefaultMinJitterRate is default min jitter rate.
	DefaultMinJitterRate float64 = -0.2
	// DefaultMaxJitterRate is default max jitter rate.
	DefaultMaxJitterRate float64 = 0.2
)

Variables

View Source
var (
	// ErrInvalidSpecFormat indicates invalid specification format.
	ErrInvalidSpecFormat = fmt.Errorf("Invalid format of specification")
)

Functions

This section is empty.

Types

type AttemptLimitingBackoff

type AttemptLimitingBackoff struct {
	// contains filtered or unexported fields
}

AttemptLimitingBackoff is a backoff which limits the number of attempts up to the specified value.

func NewAttemptLimitingBackoff

func NewAttemptLimitingBackoff(delegate Backoff, limit int) (b *AttemptLimitingBackoff, err error)

NewAttemptLimitingBackoff creates new AttemptLimitingBackoff.

func (*AttemptLimitingBackoff) NextDelayMillis

func (f *AttemptLimitingBackoff) NextDelayMillis(numAttemptsSoFar int) int64

NextDelayMillis returns the number of milliseconds to wait for before attempting a retry.

type Backoff

type Backoff interface {
	// NextDelayMillis returns the number of milliseconds to wait for before attempting a retry.
	NextDelayMillis(numAttemptsSoFar int) int64
}

Backoff controls back off between attempts in a single retry operation.

var NoDelayBackoff Backoff = &FixedBackoff{delayMillis: 0}

NoDelayBackoff returns a Backoff that will never wait between attempts. In most cases, using Backoff without delay is very dangerous.

var NoRetry Backoff = &FixedBackoff{delayMillis: -1}

NoRetry returns a Backoff indicates that no retry.

type BackoffBuilder

type BackoffBuilder struct {
	// contains filtered or unexported fields
}

BackoffBuilder is the builder for backoff.

func NewBackoffBuilder

func NewBackoffBuilder() *BackoffBuilder

NewBackoffBuilder creates new backoff builder.

func (*BackoffBuilder) BaseBackoff

func (b *BackoffBuilder) BaseBackoff(base Backoff) *BackoffBuilder

BaseBackoff sets base backoff. Base backoff could be chaining WithJitter and WithLimit number of attempts.

func (*BackoffBuilder) BaseBackoffSpec

func (b *BackoffBuilder) BaseBackoffSpec(spec string) *BackoffBuilder

BaseBackoffSpec sets specification for building base backoff. Then base backoff could be chaining WithJitter and WithLimit number of attempts.

This is the format for the specification:

// "exponential=initialDelayMillis:maxDelayMillis:multiplier" is for ExponentialBackoff.
// multiplier will be 2.0 if it's omitted.
// initialDelayMillis will be 200 if its omitted.
// maxDelayMillis will be 10000 if its omitted.
//
// "fixed=delayMillis" is for FixedBackoff. delayMillis will be 200 if its omitted
//
// "random=minDelayMillis:maxDelayMillis" is for RandomBackoff.
// minDelayMillis will be 0 if its omitted.
// maxDelayMillis will be 200 if its omitted.

To omit a value, just make it blank but keep separation ':'. For example: "exponential=12::3" means initialDelayMillis = 12, maxDelayMillis is default = 10000 and multiplier = 3

func (*BackoffBuilder) Build

func (b *BackoffBuilder) Build() (r Backoff, err error)

Build the backoff.

func (*BackoffBuilder) WithJitter

func (b *BackoffBuilder) WithJitter(jitterRate float64) *BackoffBuilder

WithJitter wraps a base backoff, adds a random jitter value to the original delay using full jitter strategy. ThejitterRate is used to calculate the lower and upper bound of the ultimate delay.

The lower bound will be ((1 - jitterRate) * originalDelay) and the upper bound will be ((1 + jitterRate) * originalDelay).

For example, if the delay returned by exponentialBackoff(long, long) is 1000 milliseconds and the provided jitter value is 0.3, the ultimate backoff delay will be chosen between 1000 * (1 - 0.3) and 1000 * (1 + 0.3) by randomer. The rate value should be between 0.0 and 1.0.

func (*BackoffBuilder) WithJitterBound

func (b *BackoffBuilder) WithJitterBound(minJitterRate, maxJitterRate float64) *BackoffBuilder

WithJitterBound similar to WithJitter but with specific min-maxJitterRate.

func (*BackoffBuilder) WithLimit

func (b *BackoffBuilder) WithLimit(limit int) *BackoffBuilder

WithLimit wraps base backoff with limiting the number of attempts up to the specified value.

Default: no limit

type ExponentialBackoff

type ExponentialBackoff struct {
	// contains filtered or unexported fields
}

ExponentialBackoff waits for an exponentially-increasing amount of time between attempts.

func NewExponentialBackoff

func NewExponentialBackoff(initialDelayMillis, maxDelayMillis int64, multiplier float64) (b *ExponentialBackoff, err error)

NewExponentialBackoff creates new ExponentialBackoff.

func (*ExponentialBackoff) NextDelayMillis

func (f *ExponentialBackoff) NextDelayMillis(numAttemptsSoFar int) (nextDelay int64)

NextDelayMillis returns the number of milliseconds to wait for before attempting a retry.

type FixedBackoff

type FixedBackoff struct {
	// contains filtered or unexported fields
}

FixedBackoff waits for a fixed delay between attempts.

func NewFixedBackoff

func NewFixedBackoff(delayMillis int64) (b *FixedBackoff, err error)

NewFixedBackoff creates new fixed backoff.

func (*FixedBackoff) NextDelayMillis

func (f *FixedBackoff) NextDelayMillis(numAttemptsSoFar int) int64

NextDelayMillis returns the number of milliseconds to wait for before attempting a retry.

type JitterAddingBackoff

type JitterAddingBackoff struct {
	// contains filtered or unexported fields
}

JitterAddingBackoff returns a Backoff that adds a random jitter value to the original delay using https://www.awsarchitectureblog.com/2015/03/backoff.html full jitter strategy.

func NewJitterAddingBackoff

func NewJitterAddingBackoff(delegate Backoff, minJitterRate, maxJitterRate float64) (b *JitterAddingBackoff, err error)

NewJitterAddingBackoff creates new JitterAddingBackoff.

func (*JitterAddingBackoff) NextDelayMillis

func (f *JitterAddingBackoff) NextDelayMillis(numAttemptsSoFar int) (nextDelay int64)

NextDelayMillis returns the number of milliseconds to wait for before attempting a retry.

type RandomBackoff

type RandomBackoff struct {
	// contains filtered or unexported fields
}

RandomBackoff computes backoff delay which is a random value between minDelayMillis} and maxDelayMillis.

func NewRandomBackoff

func NewRandomBackoff(minDelayMillis, maxDelayMillis int64) (b *RandomBackoff, err error)

NewRandomBackoff creates new RandomBackoff.

func (*RandomBackoff) NextDelayMillis

func (f *RandomBackoff) NextDelayMillis(numAttemptsSoFar int) int64

NextDelayMillis returns number of milliseconds to wait for before attempting a retry.

Jump to

Keyboard shortcuts

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