| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107 |
- package backoff
- import (
- "context"
- "time"
- )
- type ExponentialInterval struct {
- current float64
- maxInterval float64
- minInterval float64
- multiplier float64
- jitter jitter
- }
- const (
- defaultMaxInterval = float64(time.Minute)
- defaultMinInterval = float64(500 * time.Millisecond)
- defaultMultiplier = 1.5
- )
- func NewExponentialInterval(options ...ExponentialOption) *ExponentialInterval {
- jitterFactor := 0.0
- maxInterval := defaultMaxInterval
- minInterval := defaultMinInterval
- multiplier := defaultMultiplier
- var rng Random
- for _, option := range options {
- switch option.Ident() {
- case identJitterFactor{}:
- jitterFactor = option.Value().(float64)
- case identMaxInterval{}:
- maxInterval = float64(option.Value().(time.Duration))
- case identMinInterval{}:
- minInterval = float64(option.Value().(time.Duration))
- case identMultiplier{}:
- multiplier = option.Value().(float64)
- case identRNG{}:
- rng = option.Value().(Random)
- }
- }
- if minInterval > maxInterval {
- minInterval = maxInterval
- }
- if multiplier <= 1 {
- multiplier = defaultMultiplier
- }
- return &ExponentialInterval{
- maxInterval: maxInterval,
- minInterval: minInterval,
- multiplier: multiplier,
- jitter: newJitter(jitterFactor, rng),
- }
- }
- func (g *ExponentialInterval) Next() time.Duration {
- var next float64
- if g.current == 0 {
- next = g.minInterval
- } else {
- next = g.current * g.multiplier
- }
- if next > g.maxInterval {
- next = g.maxInterval
- }
- if next < g.minInterval {
- next = g.minInterval
- }
- // Apply jitter *AFTER* we calculate the base interval
- next = g.jitter.apply(next)
- g.current = next
- return time.Duration(next)
- }
- type ExponentialPolicy struct {
- cOptions []ControllerOption
- igOptions []ExponentialOption
- }
- func NewExponentialPolicy(options ...ExponentialOption) *ExponentialPolicy {
- var cOptions []ControllerOption
- var igOptions []ExponentialOption
- for _, option := range options {
- switch opt := option.(type) {
- case ControllerOption:
- cOptions = append(cOptions, opt)
- default:
- igOptions = append(igOptions, opt)
- }
- }
- return &ExponentialPolicy{
- cOptions: cOptions,
- igOptions: igOptions,
- }
- }
- func (p *ExponentialPolicy) Start(ctx context.Context) Controller {
- ig := NewExponentialInterval(p.igOptions...)
- return newController(ctx, ig, p.cOptions...)
- }
|