backoff

package module
v0.4.3 Latest Latest
Warning

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

Go to latest
Published: Aug 28, 2022 License: MIT Imports: 7 Imported by: 0

README

backoff

GoDev Workflow Status Coverage Status

Exponential backoff algorithm with randomized jitter

Example

package main

import (
        "context"
        "fmt"
        "log"
        "net/http"
        "time"

        "github.com/go-tk/backoff"
        "github.com/go-tk/optional"
)

func main() {
        ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
        _ = cancel
        b := backoff.New(backoff.Options{
                MinDelay:            optional.MakeDuration(100 * time.Millisecond), // default
                MaxDelay:            optional.MakeDuration(100 * time.Second),      // default
                DelayFactor:         optional.MakeFloat64(2),                       // default
                MaxDelayJitter:      optional.MakeFloat64(1),                       // default
                DelayFunc:           backoff.DelayWithContext(ctx),                 // with respect to ctx
                MaxNumberOfAttempts: optional.MakeInt(100),                         // default
        })
        req, err := http.NewRequestWithContext(ctx, "GET", "http://example.com/", nil)
        if err != nil {
                log.Fatal(err)
        }
        for {
                resp, err := http.DefaultClient.Do(req)
                if err != nil {
                        if err2 := b.Do(); err2 != nil { // delay
                                log.Printf("failed to back off; err=%q", err2)
                                log.Fatal(err)
                        }
                        continue // retry
                }
                resp.Body.Close()
                if resp.StatusCode/100 == 5 {
                        err := fmt.Errorf("http server error; httpStatusCode=%v", resp.StatusCode)
                        if err2 := b.Do(); err2 != nil { // delay
                                log.Printf("failed to back off; err=%q", err2)
                                log.Fatal(err)
                        }
                        continue // retry
                }
                fmt.Println(resp.StatusCode)
                return
        }
        // Output:
        // 200
}

Documentation

Overview

Package backoff implements the exponential backoff algorithm with randomized jitter.

Index

Examples

Constants

This section is empty.

Variables

View Source
var ErrTooManyAttempts = errors.New("backoff: too many attempts")

ErrTooManyAttempts is returned when the maximum number of attempts to back off has been reached.

Functions

This section is empty.

Types

type Backoff

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

Backoff represents an instance of the exponential backoff algorithm.

Example
package main

import (
	"context"
	"fmt"
	"log"
	"net/http"
	"time"

	"github.com/go-tk/backoff"
	"github.com/go-tk/optional"
)

func main() {
	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
	_ = cancel
	b := backoff.New(backoff.Options{
		MinDelay:            optional.MakeDuration(100 * time.Millisecond), // default
		MaxDelay:            optional.MakeDuration(100 * time.Second),      // default
		DelayFactor:         optional.MakeFloat64(2),                       // default
		MaxDelayJitter:      optional.MakeFloat64(1),                       // default
		DelayFunc:           backoff.DelayWithContext(ctx),                 // with respect to ctx
		MaxNumberOfAttempts: optional.MakeInt(100),                         // default
	})
	req, err := http.NewRequestWithContext(ctx, "GET", "http://example.com/", nil)
	if err != nil {
		log.Fatal(err)
	}
	for {
		resp, err := http.DefaultClient.Do(req)
		if err != nil {
			if err2 := b.Do(); err2 != nil { // delay
				log.Printf("failed to back off; err=%q", err2)
				log.Fatal(err)
			}
			continue // retry
		}
		resp.Body.Close()
		if resp.StatusCode/100 == 5 {
			err := fmt.Errorf("http server error; httpStatusCode=%v", resp.StatusCode)
			if err2 := b.Do(); err2 != nil { // delay
				log.Printf("failed to back off; err=%q", err2)
				log.Fatal(err)
			}
			continue // retry
		}
		fmt.Println(resp.StatusCode)
		return
	}
}
Output:
200

func New

func New(options Options) *Backoff

New creates an instance of the exponential backoff algorithm with the given options.

func (*Backoff) Do

func (b *Backoff) Do() error

Do delays for a time period determined based on the options.

type DelayFunc

type DelayFunc func(timedOut <-chan struct{}) (err error)

DelayFunc is the type of the function blocking until the timed-out event happens.

func DelayWithContext

func DelayWithContext(ctx context.Context) DelayFunc

DelayWithContext makes a DelayFunc with respect to the given ctx.

type Options

type Options struct {
	// Default value is 100ms.
	// Value <= 0 is equivalent to default value.
	MinDelay optional.Duration

	// Default value is 100s.
	// Value <= 0 is equivalent to default value.
	MaxDelay optional.Duration

	// Default value is 2.
	// Value < 1 is equivalent to default value.
	DelayFactor optional.Float64

	// Default value is 1.
	// Value <= 0 means no delay jitter.
	// Value > 1 is equivalent to 1.
	MaxDelayJitter optional.Float64

	// Default value is:
	//  func(timedOut <-chan struct{}) error {
	//      <-timedOut
	//      return nil
	//  }
	DelayFunc DelayFunc

	// Default value is 100.
	// Value < 0 means no limit on the number of attempts.
	MaxNumberOfAttempts optional.Int
}

Options represents options for backoffs.

The pseudo code for the delay calculation:

if delay is not initialized
    delay = MIN_DELAY
else
    delay = min(delay * DELAY_FACTOR, MAX_DELAY)
delay_jitter = random(-MAX_DELAY_JITTER, MAX_DELAY_JITTER)
delay_with_jitter = delay * (1 + delay_jitter)

Jump to

Keyboard shortcuts

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