-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathbackoff.go
75 lines (64 loc) · 1.26 KB
/
backoff.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
package stubborn
import (
"math"
"math/rand"
"time"
)
const eulersNumber = 2.71828
type backoff struct {
attempt float64
Exponentiation float64
//Jitter eases contention by randomizing backoff steps
Jitter bool
//Min and Max are the minimum and maximum values of the counter
Min, Max time.Duration
}
func (b *backoff) Duration() time.Duration {
d := b.forAttempt(b.attempt)
b.attempt++
return d
}
func (b *backoff) forAttempt(attempt float64) time.Duration {
// Zero-values are nonsensical, so we use
// them to apply defaults
min := b.Min
if min <= 0 {
min = 100 * time.Millisecond
}
max := b.Max
if max <= 0 {
max = 10 * time.Second
}
if min >= max {
// short-circuit
return max
}
var exp = b.Exponentiation
if b.Exponentiation == 0 {
exp = eulersNumber
}
minf := float64(min)
durf := minf * math.Pow(exp, attempt)
if b.Jitter {
durf = rand.Float64()*(durf-minf) + minf
}
if durf > math.MaxInt64 {
return max
}
dur := time.Duration(durf)
if dur < min {
return min
}
if dur > max {
return max
}
return dur
}
// Reset restarts the current attempt counter at zero.
func (b *backoff) Reset() {
b.attempt = 0
}
// Attempt returns the current attempt counter value.
func (b *backoff) Attempt() float64 {
return b.attempt
}