...

Source file src/github.com/lestrrat-go/backoff/v2/exponential.go

Documentation: github.com/lestrrat-go/backoff/v2

     1  package backoff
     2  
     3  import (
     4  	"context"
     5  	"time"
     6  )
     7  
     8  type ExponentialInterval struct {
     9  	current     float64
    10  	maxInterval float64
    11  	minInterval float64
    12  	multiplier  float64
    13  	jitter      jitter
    14  }
    15  
    16  const (
    17  	defaultMaxInterval = float64(time.Minute)
    18  	defaultMinInterval = float64(500 * time.Millisecond)
    19  	defaultMultiplier  = 1.5
    20  )
    21  
    22  func NewExponentialInterval(options ...ExponentialOption) *ExponentialInterval {
    23  	jitterFactor := 0.0
    24  	maxInterval := defaultMaxInterval
    25  	minInterval := defaultMinInterval
    26  	multiplier := defaultMultiplier
    27  	var rng Random
    28  
    29  	for _, option := range options {
    30  		switch option.Ident() {
    31  		case identJitterFactor{}:
    32  			jitterFactor = option.Value().(float64)
    33  		case identMaxInterval{}:
    34  			maxInterval = float64(option.Value().(time.Duration))
    35  		case identMinInterval{}:
    36  			minInterval = float64(option.Value().(time.Duration))
    37  		case identMultiplier{}:
    38  			multiplier = option.Value().(float64)
    39  		case identRNG{}:
    40  			rng = option.Value().(Random)
    41  		}
    42  	}
    43  
    44  	if minInterval > maxInterval {
    45  		minInterval = maxInterval
    46  	}
    47  	if multiplier <= 1 {
    48  		multiplier = defaultMultiplier
    49  	}
    50  
    51  	return &ExponentialInterval{
    52  		maxInterval: maxInterval,
    53  		minInterval: minInterval,
    54  		multiplier:  multiplier,
    55  		jitter:      newJitter(jitterFactor, rng),
    56  	}
    57  }
    58  
    59  func (g *ExponentialInterval) Next() time.Duration {
    60  	var next float64
    61  	if g.current == 0 {
    62  		next = g.minInterval
    63  	} else {
    64  		next = g.current * g.multiplier
    65  	}
    66  
    67  	if next > g.maxInterval {
    68  		next = g.maxInterval
    69  	}
    70  	if next < g.minInterval {
    71  		next = g.minInterval
    72  	}
    73  
    74  	// Apply jitter *AFTER* we calculate the base interval
    75  	next = g.jitter.apply(next)
    76  	g.current = next
    77  	return time.Duration(next)
    78  }
    79  
    80  type ExponentialPolicy struct {
    81  	cOptions  []ControllerOption
    82  	igOptions []ExponentialOption
    83  }
    84  
    85  func NewExponentialPolicy(options ...ExponentialOption) *ExponentialPolicy {
    86  	var cOptions []ControllerOption
    87  	var igOptions []ExponentialOption
    88  
    89  	for _, option := range options {
    90  		switch opt := option.(type) {
    91  		case ControllerOption:
    92  			cOptions = append(cOptions, opt)
    93  		default:
    94  			igOptions = append(igOptions, opt)
    95  		}
    96  	}
    97  
    98  	return &ExponentialPolicy{
    99  		cOptions:  cOptions,
   100  		igOptions: igOptions,
   101  	}
   102  }
   103  
   104  func (p *ExponentialPolicy) Start(ctx context.Context) Controller {
   105  	ig := NewExponentialInterval(p.igOptions...)
   106  	return newController(ctx, ig, p.cOptions...)
   107  }
   108  

View as plain text