blob: 94f411ac28ec2b8f0930c17703df6a57d0792a62 [file] [log] [blame] [edit]
package apidApigeeSync
import (
"math"
"math/rand"
"time"
)
const defaultInitial time.Duration = 200 * time.Millisecond
const defaultMax time.Duration = 10 * time.Second
const defaultFactor float64 = 2
type Backoff struct {
attempt int
initial, max time.Duration
jitter bool
backoffStrategy func() time.Duration
}
type ExponentialBackoff struct {
Backoff
factor float64
}
func NewExponentialBackoff(initial, max time.Duration, factor float64, jitter bool) *ExponentialBackoff {
backoff := &ExponentialBackoff{}
if initial <= 0 {
initial = defaultInitial
}
if max <= 0 {
max = defaultMax
}
if factor <= 0 {
factor = defaultFactor
}
backoff.initial = initial
backoff.max = max
backoff.attempt = 0
backoff.factor = factor
backoff.jitter = jitter
backoff.backoffStrategy = backoff.exponentialBackoffStrategy
return backoff
}
func (b *Backoff) Duration() time.Duration {
d := b.backoffStrategy()
b.attempt++
return d
}
func (b *ExponentialBackoff) exponentialBackoffStrategy() time.Duration {
initial := float64(b.Backoff.initial)
attempt := float64(b.Backoff.attempt)
duration := initial * math.Pow(b.factor, attempt)
if duration > math.MaxInt64 {
return b.max
}
dur := time.Duration(duration)
if b.jitter {
duration = (rand.Float64()*(duration-initial) + initial)
}
if dur > b.max {
return b.max
}
log.Debugf("Backing off for %d ms", int64(dur/time.Millisecond))
return dur
}
func (b *Backoff) Reset() {
b.attempt = 0
}
func (b *Backoff) Attempt() int {
return b.attempt
}