src

Go monorepo.
git clone git://code.dwrz.net/src
Log | Files | Refs

jitter_backoff.go (1332B)


      1 package retry
      2 
      3 import (
      4 	"math"
      5 	"time"
      6 
      7 	"github.com/aws/aws-sdk-go-v2/internal/rand"
      8 	"github.com/aws/aws-sdk-go-v2/internal/timeconv"
      9 )
     10 
     11 // ExponentialJitterBackoff provides backoff delays with jitter based on the
     12 // number of attempts.
     13 type ExponentialJitterBackoff struct {
     14 	maxBackoff time.Duration
     15 	// precomputed number of attempts needed to reach max backoff.
     16 	maxBackoffAttempts float64
     17 
     18 	randFloat64 func() (float64, error)
     19 }
     20 
     21 // NewExponentialJitterBackoff returns an ExponentialJitterBackoff configured
     22 // for the max backoff.
     23 func NewExponentialJitterBackoff(maxBackoff time.Duration) *ExponentialJitterBackoff {
     24 	return &ExponentialJitterBackoff{
     25 		maxBackoff: maxBackoff,
     26 		maxBackoffAttempts: math.Log2(
     27 			float64(maxBackoff) / float64(time.Second)),
     28 		randFloat64: rand.CryptoRandFloat64,
     29 	}
     30 }
     31 
     32 // BackoffDelay returns the duration to wait before the next attempt should be
     33 // made. Returns an error if unable get a duration.
     34 func (j *ExponentialJitterBackoff) BackoffDelay(attempt int, err error) (time.Duration, error) {
     35 	if attempt > int(j.maxBackoffAttempts) {
     36 		return j.maxBackoff, nil
     37 	}
     38 
     39 	b, err := j.randFloat64()
     40 	if err != nil {
     41 		return 0, err
     42 	}
     43 
     44 	// [0.0, 1.0) * 2 ^ attempts
     45 	ri := int64(1 << uint64(attempt))
     46 	delaySeconds := b * float64(ri)
     47 
     48 	return timeconv.FloatSecondsDur(delaySeconds), nil
     49 }