backoff/utilities/jitter.go

74 lines
1.3 KiB
Go

package utilities
import (
"math"
"math/rand/v2"
"time"
)
var (
ApplyJitter = DefaultApplyJitter
)
const (
maxInt64 = math.MaxInt64
minInt64 = math.MinInt64
)
func satAdd(a, b int64) int64 {
switch {
case b > 0 && a > maxInt64-b:
return maxInt64
case b < 0 && a < minInt64-b:
return minInt64
default:
return a + b
}
}
func satSub(a, b int64) int64 {
switch {
case b > 0 && a < minInt64+b:
return minInt64
case b < 0 && a > maxInt64+b:
return maxInt64
default:
return a - b
}
}
func DefaultApplyJitter(pauseDuration time.Duration, jitter time.Duration) time.Duration {
switch {
case pauseDuration <= 0:
return 0
case jitter == 0:
return pauseDuration
case jitter < 0:
jitter = -jitter
case jitter > pauseDuration:
pauseDuration, jitter = jitter, pauseDuration
}
min := satSub(pauseDuration.Nanoseconds(), jitter.Nanoseconds())
if min < 0 {
min = 0
}
max := satAdd(pauseDuration.Nanoseconds(), jitter.Nanoseconds())
if max <= min {
return time.Duration(min)
}
var maxExcl int64
if max == math.MaxInt64 {
span := max - min
if span == math.MaxInt64 {
return time.Duration(rand.Int64N(math.MaxInt64) + min)
}
n := rand.Int64N(span + 1)
return time.Duration(min + n)
}
maxExcl = max + 1
return time.Duration(min + rand.Int64N(maxExcl-min))
}