• Home
  • History
  • Annotate
Name Date Size #Lines LOC

..27-Nov-2021-

.gitignoreH A D27-Nov-2021275 1511

.golangci.ymlH A D27-Nov-2021111 86

ChangesH A D27-Nov-2021175 96

LICENSEH A D27-Nov-20211 KiB2217

README.mdH A D27-Nov-20215.1 KiB184140

backoff.goH A D27-Nov-2021677 3218

constant.goH A D27-Nov-20211.3 KiB6755

controller.goH A D27-Nov-20211.8 KiB10086

doc.goH A D27-Nov-2021243 61

exponential.goH A D27-Nov-20212.3 KiB10891

interface.goH A D27-Nov-2021534 3120

jitter.goH A D27-Nov-20211.5 KiB6040

null.goH A D27-Nov-2021967 5241

options.goH A D27-Nov-20213.8 KiB12870

README.md

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
184