retry

package module
v0.4.0 Latest Latest
Warning

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

Go to latest
Published: Apr 19, 2026 License: MIT Imports: 4 Imported by: 1

README

Retry

Go Reference Go Report Card Tests Coverage Status

This is retry, a Go library for retrying function calls that may fail.

It lets you limit the number of retries and the time spent retrying. You can configure the interval between tries and do exponential backoff. You can add random jitter to the time interval. And you can supply a function for discriminating between retryable and non-retryable errors.

Usage

tr := retry.Tryer{
  Max:   5,
  Delay: 100 * time.Millisecond,
  Scale: 0.25,
}
err := tr.Try(ctx, myFunc)

Seriously, another retry library for Go?

There are already some excellent retry libraries for Go. But I did not find one to be as complete and as ergonomic as this simple API. For details, please see the Godoc.

Documentation

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type ContextError

type ContextError struct {
	Err error
}

ContextError is an error returned by Tryer.Try wrapping the context error when the context is canceled.

func (ContextError) Error

func (e ContextError) Error() string

func (ContextError) Unwrap

func (e ContextError) Unwrap() error

type MaxTriesError

type MaxTriesError struct {
	Err error
}

MaxTriesError is an error returned by Tryer.Try wrapping the error returned by the function after the maximum number of tries is reached.

func (MaxTriesError) Error

func (e MaxTriesError) Error() string

func (MaxTriesError) Unwrap

func (e MaxTriesError) Unwrap() error

type Tryer

type Tryer struct {
	// Max is the maximum number of tries to make.
	// [Tryer.Try] always makes at least one attempt.
	// Leaving this set to 0 is the same as setting it to 1.
	// A negative value means there is no limit on the number of attempts.
	Max int

	// Delay is the initial delay between attempts.
	// Be sure to set this to a non-zero value to avoid an expensive busy loop.
	// The delay can increase after each attempt; see the Scale field below.
	Delay time.Duration

	// Jitter is the maximum amount of random jitter to add to,
	// or subtract from,
	// the delay on each attempt.
	// This value is silently limited to each iteration's delay.
	Jitter time.Duration

	// Scale increases the delay after each attempt, multiplying it by 1+Scale.
	// For example, setting this to 1 will double the delay after each attempt.
	// Leaving this set to 0 means the delay will not scale.
	Scale float64

	// MaxDelay is the maximum delay between attempts.
	// Scale will not cause the delay to exceed this value.
	// (However, random Jitter may still be added.)
	// A value of 0 means there is no maximum delay.
	MaxDelay time.Duration

	// IsRetryable is an optional function that determines whether an error is retryable.
	// If it is nil, all errors are considered retryable.
	// It receives the context, the error, and the number of the next attempt (starting at 1).
	IsRetryable func(context.Context, error, int) bool

	// OnRetry is an optional function that is called after a retryable error in the callback.
	// This can be used for logging or other side effects.
	// It receives the context, the error, the number of the next attempt, and the delay before the next attempt.
	OnRetry func(context.Context, error, int, time.Duration)

	// After is an optional function returning a channel that sends the current time after the specified duration.
	// If it is nil, [time.After] is used.
	After func(time.Duration) <-chan time.Time

	// Rand is an optional function that returns a random float64 in the range [0, 1).
	// If it is nil, [rand.Float64] is used.
	Rand func() float64
}

Tryer runs a function via its Try method one or more times until it succeeds, or a maximum number of retries is reached, or it encounters an unretryable error.

It waits for a specified interval between attempts, optionally adding a random amount of jitter to the delay. The interval can optionally scale up after each attempt, for exponential backoff.

There is no MaxTime field. To limit the total time spent retrying, set a deadline on the context passed to Tryer.Try.

Example
package main

import (
	"context"
	"fmt"
	"os"
	"time"

	"github.com/bobg/retry"
)

func main() {
	// With the following config,
	// tr.Try will try to execute the function up to 5 times.
	// It will wait 100ms after the first attempt, plus or minus up to 50ms of jitter;
	// 150 (100 × 1.5) after the second, plus or minus up to 50ms;
	// 225 (100 × 1.5 × 1.5) after the third, plus or minus up to 50ms;
	// etc.
	tr := retry.Tryer{
		Max:    5,
		Delay:  100 * time.Millisecond,
		Jitter: 50 * time.Millisecond,
		Scale:  0.5,
		OnRetry: func(_ context.Context, err error, _ int, delay time.Duration) {
			fmt.Fprintf(os.Stderr, "Error, will retry after %s: %s\n", delay, err)
		},
	}

	// This context makes sure tr.Try spends no more than about 1 second doing retries.
	ctx, cancel := context.WithTimeout(context.Background(), time.Second)
	defer cancel()

	// Retry a simple function that fails on its first two tries and succeeds on its third.
	err := tr.Try(ctx, func(n int) error {
		if n < 2 {
			fmt.Printf("Failed on try #%d\n", n)
			return fmt.Errorf("failed on try #%d", n)
		}
		fmt.Printf("Succeeded on try #%d\n", n)
		return nil
	})
	if err != nil {
		fmt.Printf("Error: %s\n", err)
	}

}
Output:
Failed on try #0
Failed on try #1
Succeeded on try #2

func (Tryer) Try

func (tr Tryer) Try(ctx context.Context, f func(int) error) error

Try runs the provided function one or more times until it succeeds, or the provided context is canceled, or certain other conditions are met - see Tryer.

The number of the current attempt is passed to the function as an argument, starting at 0 for the first attempt.

If f succeeds (i.e., returns nil), Try returns nil. Otherwise it returns one of these error-wrapper types: UnretryableError, MaxTriesError, or ContextError.

type UnretryableError

type UnretryableError struct {
	Err error
}

UnretryableError is an error returned by Tryer.Try wrapping the error returned by the function when it is determined to be unretryable.

func (UnretryableError) Error

func (e UnretryableError) Error() string

func (UnretryableError) Unwrap

func (e UnretryableError) Unwrap() error

Jump to

Keyboard shortcuts

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