Gennady Lipenkov fcfbdc6b08 Update Yandex.Cloud go packages "go-genproto" and "go-sdk"
'go mod vendor' included
2020-06-17 12:35:43 +03:00

41 lines
1.2 KiB
Go

package retry
import (
"math"
"math/rand"
"time"
)
type BackoffFunc func(attempt int) time.Duration
func BackoffLinearWithJitter(waitBetween time.Duration, jitterFraction float64) BackoffFunc {
return func(attempt int) time.Duration {
return jitterAround(waitBetween, jitterFraction)
}
}
func BackoffExponentialWithJitter(base time.Duration, cap time.Duration) BackoffFunc {
return func(attempt int) time.Duration {
to := getExponentialTimeout(attempt, base)
// Using float types here, because exponential time can be really big, and converting it to time.Duration may
// result in undefined behaviour. Its safe conversion, when we have compared it to our 'cap' value.
if to > float64(cap) {
to = float64(cap)
}
return time.Duration(to/2 + to/2*rand.Float64())
}
}
func getExponentialTimeout(attempt int, base time.Duration) float64 {
// pow 3: 50ms, 150ms, 450ms, 1.35s, 4.05s, 12.15s - Now.
// pow 2: 50ms, 100ms, 200ms, 400ms, 800ms, 1.6s - Previous.
mult := math.Pow(3, float64(attempt))
return float64(base) * mult
}
func jitterAround(duration time.Duration, jitter float64) time.Duration {
multiplier := jitter * (rand.Float64()*2 - 1)
return time.Duration(float64(duration) * (1 + multiplier))
}