retry

package module
v1.2.0 Latest Latest
Warning

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

Go to latest
Published: Dec 29, 2023 License: MIT Imports: 4 Imported by: 22

README

Build Status PkgGoDev

retry

Simple utils for exponential back off.

SYNOPSIS

https://golang.ir/play/p/epPT1bJoU2e

package main

import (
    "context"
    "errors"
    "fmt"
    "time"

    "github.com/shogo82148/go-retry"
)

type Result int

func DoSomething(ctx context.Context) (Result, error) {
    // do something here that should to do exponential backoff https://en.wikipedia.org/wiki/Exponential_backoff
    return 0, errors.New("fails")
}

var policy = retry.Policy{
    MinDelay: 100 * time.Millisecond,
    MaxDelay: time.Second,
    MaxCount: 10,
}

func DoSomethingWithRetry(ctx context.Context) (Result, error) {
    retrier := policy.Start(ctx)
    for retrier.Continue() {
        if res, err := DoSomething(ctx); err == nil {
            return res, nil
        }
    }
    return 0, errors.New("tried very hard, but no luck")
}

func main() {
    fmt.Println(DoSomethingWithRetry(context.Background()))
}

https://golang.ir/play/p/aEYgJuXsatd

package main

import (
    "context"
    "errors"
    "fmt"
    "time"

    "github.com/shogo82148/go-retry"
)

func DoSomething(ctx context.Context) error {
    // do something here that should to do exponential backoff https://en.wikipedia.org/wiki/Exponential_backoff
    return errors.New("fails")
}

var policy = retry.Policy{
    MinDelay: 100 * time.Millisecond,
    MaxDelay: time.Second,
    MaxCount: 10,
}

func DoSomethingWithRetry(ctx context.Context) error {
    return policy.Do(ctx, func() error {
        return DoSomething(ctx)
    })
}

func main() {
    fmt.Println(DoSomethingWithRetry(context.Background()))
}
package main

import (
    "context"
    "errors"
    "fmt"
    "time"

    "github.com/shogo82148/go-retry"
)

type Result int

func DoSomething(ctx context.Context) (Result, error) {
    // do something here that should to do exponential backoff https://en.wikipedia.org/wiki/Exponential_backoff
    return 0, errors.New("fails")
}

var policy = retry.Policy{
    MinDelay: 100 * time.Millisecond,
    MaxDelay: time.Second,
    MaxCount: 10,
}

func DoSomethingWithRetry(ctx context.Context) (Result, error) {
    return retry.DoValue(ctx, policy, DoSomething)
}

func main() {
    fmt.Println(DoSomethingWithRetry(context.Background()))
}

PRIOR ARTS

This package is based on lestrrat-go/backoff and Yak Shaving With Backoff Libraries in Go. lestrrat-go/backoff's interface is so cool, but I want more simple one.

Songmu/retry is very simple, but it is too simple for me.

Documentation

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func DoValue added in v1.2.0

func DoValue[T any](ctx context.Context, policy *Policy, f func() (T, error)) (T, error)

DoValue executes f with retrying policy. It is a shorthand of Policy.Start and Retrier.Continue. If f returns an error, retry to execute f until f returns nil error. If the error implements interface{ Temporary() bool } and Temporary() returns false, DoValue doesn't retry and returns the error.

Example
policy := &retry.Policy{
	MaxCount: 3,
}

count := 0
_, err := retry.DoValue(context.Background(), policy, func() (int, error) {
	count++
	fmt.Printf("#%d: unstable func is called!\n", count)
	return 0, errors.New("some error!")
})
if err != nil {
	fmt.Println(err)
}
Output:

#1: unstable func is called!
#2: unstable func is called!
#3: unstable func is called!
some error!

func MarkPermanent

func MarkPermanent(err error) error

MarkPermanent marks err as a permanent error. It returns the error that implements interface{ Temporary() bool } and Temporary() returns false.

Example
policy := &retry.Policy{}

err := policy.Do(context.Background(), func() error {
	fmt.Println("unstable func is called!")
	return retry.MarkPermanent(errors.New("some error!"))
})
fmt.Println(err)
Output:

unstable func is called!
some error!

Types

type Policy

type Policy struct {
	// MinDelay is a first delay for retrying.
	// Zero or negative value means no delay.
	MinDelay time.Duration

	// MaxDelay is the maximum delay for retrying.
	// If MaxDelay is less than MinDelay, MinDelay is used as the maximum delay.
	MaxDelay time.Duration

	// MaxCount is max retry count.
	// Zero or negative value means retry forever.
	MaxCount int

	// Jitter adds random delay.
	// Zero means no jitter.
	// Negative value shorten the delay.
	Jitter time.Duration
}

Policy is a retry policy.

func (*Policy) Do

func (p *Policy) Do(ctx context.Context, f func() error) error

Do executes f with retrying policy. It is a shorthand of Policy.Start and Retrier.Continue. If f returns an error, retry to execute f until f returns nil error. If the error implements interface{ Temporary() bool } and Temporary() returns false, Do doesn't retry and returns the error.

Example
policy := &retry.Policy{
	MaxCount: 3,
}

count := 0
err := policy.Do(context.Background(), func() error {
	count++
	fmt.Printf("#%d: unstable func is called!\n", count)
	return errors.New("some error!")
})
if err != nil {
	fmt.Println(err)
}
Output:

#1: unstable func is called!
#2: unstable func is called!
#3: unstable func is called!
some error!

func (*Policy) Start

func (p *Policy) Start(ctx context.Context) *Retrier

Start starts retrying

Example
count := 0
unstableFunc := func() error {
	count++
	fmt.Printf("#%d: unstableFunc is called!\n", count)
	if count < 3 {
		return errors.New("some error!")
	}
	return nil
}

policy := &retry.Policy{}
retrier := policy.Start(context.Background())
for retrier.Continue() {
	err := unstableFunc()
	if err == nil {
		fmt.Println("Success")
		break
	}
}
if err := retrier.Err(); err != nil {
	log.Fatal(err)
}
Output:

#1: unstableFunc is called!
#2: unstableFunc is called!
#3: unstableFunc is called!
Success

type Retrier

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

Retrier handles retrying.

func (*Retrier) Continue

func (r *Retrier) Continue() bool

Continue returns whether retrying should be continued.

func (*Retrier) Err added in v1.1.0

func (r *Retrier) Err() error

Err return the error that occurred during deploy.

Jump to

Keyboard shortcuts

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