-
Notifications
You must be signed in to change notification settings - Fork 894
/
backoff.go
59 lines (50 loc) · 1.97 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
package das
import (
"time"
)
var (
// first retry attempt should happen after defaultBackoffInitialInterval
defaultBackoffInitialInterval = time.Minute
// next retry attempt will happen with delay of previous one multiplied by defaultBackoffMultiplier
defaultBackoffMultiplier = 4
// after defaultBackoffMaxRetryCount amount of attempts retry backoff interval will stop growing
// and each retry attempt will produce WARN log
defaultBackoffMaxRetryCount = 4
)
// retryStrategy defines a backoff for retries.
type retryStrategy struct {
// attempts delays will follow durations stored in retryIntervals
retryIntervals []time.Duration
}
// newRetryStrategy creates and initializes a new retry backoff.
func newRetryStrategy(retryIntervals []time.Duration) retryStrategy {
return retryStrategy{retryIntervals: retryIntervals}
}
// nextRetry creates a retry attempt with a backoff delay based on the retry backoff.
// It takes the number of retry attempts and the time of the last attempt as inputs and returns a
// retry instance and a boolean value indicating whether the retries amount have exceeded.
func (s retryStrategy) nextRetry(lastRetry retryAttempt, lastAttempt time.Time,
) (retry retryAttempt, retriesExceeded bool) {
lastRetry.count++
if len(s.retryIntervals) == 0 {
return lastRetry, false
}
if lastRetry.count > len(s.retryIntervals) {
// try count exceeded backoff try limit
lastRetry.after = lastAttempt.Add(s.retryIntervals[len(s.retryIntervals)-1])
return lastRetry, true
}
lastRetry.after = lastAttempt.Add(s.retryIntervals[lastRetry.count-1])
return lastRetry, false
}
// exponentialBackoff generates an array of time.Duration values using an exponential growth
// multiplier.
func exponentialBackoff(baseInterval time.Duration, multiplier, amount int) []time.Duration {
backoff := make([]time.Duration, 0, amount)
next := baseInterval
for i := 0; i < amount; i++ {
backoff = append(backoff, next)
next *= time.Duration(multiplier)
}
return backoff
}