...

Text file src/github.com/lestrrat-go/backoff/v2/README.md

Documentation: github.com/lestrrat-go/backoff/v2

     1# backoff ![](https://github.com/lestrrat-go/backoff/workflows/CI/badge.svg) [![Go Reference](https://pkg.go.dev/badge/github.com/lestrrat-go/backoff/v2.svg)](https://pkg.go.dev/github.com/lestrrat-go/backoff/v2)
     2
     3Idiomatic backoff for Go
     4
     5This library is an implementation of backoff algorithm for retrying operations
     6in an idiomatic Go way. It respects `context.Context` natively, and the critical
     7notifications are done through *channel operations*, allowing you to write code 
     8that is both more explicit and flexibile.
     9
    10For a longer discussion, [please read this article](https://medium.com/@lestrrat/yak-shaving-with-backoff-libraries-in-go-80240f0aa30c)
    11
    12# IMPORT
    13
    14```go
    15import "github.com/lestrrat-go/backoff/v2"
    16```
    17
    18# SYNOPSIS
    19
    20```go
    21func ExampleExponential() {
    22  p := backoff.Exponential(
    23    backoff.WithMinInterval(time.Second),
    24    backoff.WithMaxInterval(time.Minute),
    25    backoff.WithJitterFactor(0.05),
    26  )
    27
    28  flakyFunc := func(a int) (int, error) {
    29    // silly function that only succeeds if the current call count is
    30    // divisible by either 3 or 5 but not both
    31    switch {
    32    case a%15 == 0:
    33      return 0, errors.New(`invalid`)
    34    case a%3 == 0 || a%5 == 0:
    35      return a, nil
    36    }
    37    return 0, errors.New(`invalid`)
    38  }
    39
    40  ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
    41  defer cancel()
    42
    43  retryFunc := func(v int) (int, error) {
    44    b := p.Start(ctx)
    45    for backoff.Continue(b) {
    46      x, err := flakyFunc(v)
    47      if err == nil {
    48        return x, nil
    49      }
    50    }
    51    return 0, errors.New(`failed to get value`)
    52  }
    53
    54  retryFunc(15)
    55}
    56```
    57
    58# POLICIES
    59
    60Policy objects describe a backoff policy, and are factories to create backoff Controller objects.
    61Controller objects does the actual coordination.
    62Create a new controller for each invocation of a backoff enabled operation.
    63This way the controller object is protected from concurrent access (if you have one) and can easily be discarded
    64
    65## Null
    66
    67A null policy means there's no backoff. 
    68
    69For example, if you were to support both using and not using a backoff in your code you can say
    70
    71```go
    72  var p backoff.Policy
    73  if useBackoff {
    74    p = backoff.Exponential(...)
    75  } else {
    76    p = backoff.Null()
    77  }
    78  c := p.Start(ctx)
    79  for backoff.Continue(c) {
    80    if err := doSomething(); err != nil {
    81      continue
    82    }
    83    return
    84  }
    85```
    86
    87Instead of
    88
    89```go
    90  if useBackoff {
    91    p := backoff.Exponential(...)
    92    c := p.Start(ctx)
    93    for backoff.Continue(c) {
    94      if err := doSomething(); err != nil {
    95        continue
    96      }
    97      return
    98    }
    99  } else {
   100    if err := doSomething(); err != nil {
   101      continue
   102    }
   103  }
   104```
   105
   106## Constant
   107
   108A constant policy implements are backoff where the intervals are always the same
   109
   110## Exponential
   111
   112This is the most "common" of the backoffs. Intervals between calls are spaced out such that as you keep retrying, the intervals keep increasing.
   113
   114# FAQ
   115
   116## I'm getting "package github.com/lestrrat-go/backoff/v2: no Go files in /go/src/github.com/lestrrat-go/backoff/v2"
   117
   118You are using Go in GOPATH mode, which was the way before [Go Modules](https://blog.golang.org/using-go-modules) were introduced in Go 1.11 (Aug 2018).
   119GOPATH has slowly been phased out, and in Go 1.14 onwards, Go Modules pretty much Just Work.
   120Go 1.16 introduced more visible changes that forces users to be aware of the existance of go.mod files.
   121
   122The short answer when you you get the above error is: **Migrate to using Go Modules**.
   123This is simple: All you need to do is to include a go.mod (and go.sum) file to your library or app.
   124
   125For example, if you have previously been doing this:
   126
   127```
   128git clone git@github.com:myusername/myawesomeproject.git
   129cd myawesomeproject
   130go get ./...
   131```
   132
   133First include go.mod and go.sum in your repository:
   134
   135```
   136git clone git@github.com:myusername/myawesomeproject.git
   137cd myawesomeproject
   138go mod init
   139go mod tidy
   140git add go.mod go.sum
   141git commit -m "Add go.mod and go.sum" -a
   142git push 
   143```
   144
   145Then from subsequent calls:
   146
   147```
   148git clone git@github.com:myusername/myawesomeproject.git
   149cd myawesomeproject
   150go build # or go test, or go run, or whatever.
   151```
   152
   153This will tell go to respect tags, and will automatically pick up the latest version of github.com/lestrrat-go/backoff
   154
   155If you really can't do this, then the quick and dirty workaround is to just copy the files over to /v2 directory of this library
   156
   157```
   158BACKOFF=github.com/lestrrat-go/backoff
   159go get github.com/lestrrat-go/backoff
   160if [[ if ! -d "$GOPATH/src/$BACKOFF/v2" ]]; then
   161  mkdir "$GOPATH/src/$BACKOFF/v2" # just to make sure it exists
   162fi
   163cp "$GOPATH/src/$BACKOFF/*.go" "$GOPATH/src/$BACKOFF/v2"
   164
   165git clone git@github.com:myusername/myawesomeproject.git
   166cd myawesomeproject
   167go get ./...
   168```
   169
   170## Why won't you just add the files in /v2?
   171
   172Because it's hard to maintain multiple sources of truth. Sorry, I don't get paid to do this.
   173I will not hold anything against you if you decided to fork this to your repository, and move files to your own /v2 directory.
   174Then, if you have a go.mod in your app, you can just do
   175
   176```
   177go mod edit -replace github.com/lestrrat-go/backoff/v2=github.com/myusername/myawesomemfork/v2
   178```
   179
   180Oh, wait, then you already have go.mod, so this is a non-issue. 
   181
   182...Yeah, just migrate to using go modules, please?
   183

View as plain text