Skip to content

shogo82148/go-retry

Repository files navigation

Build Status PkgGoDev Coverage Status

retry

Simple utils for exponential back off.

SYNOPSIS

Do

package main

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

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

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()))
}

DoValue

package main

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

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

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()))
}

Continue

package main

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

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

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()))
}

BREAKING CHANGES

In v1, if an error implemented the Temporary() method, the retry mechanism was modified to respect the result of the method.

In v2, the package doesn't check the Temporary() method. The retry mechanism will proceed unless the error is marked as non-retryable by MarkPermanent.

If you want the same behavior as v1, you need to rewrite it as follows:

// v1 code
policy.Do(func() error {
    return DoSomething()
})

// v2 code
policy.Do(func() error {
    err := DoSomething()

    interface temporary {
        Temporary() bool
    }
    var tmp temporary
    if errors.As(err, &tmp) && !tmp.Temporary() {
        return retry.MarkPermanent(err)
    }
    return err
})

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 a simpler one.

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

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Contributors 4

  •  
  •  
  •  
  •  

Languages