| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566 |
- package waiter
- import (
- "fmt"
- "math"
- "time"
- "github.com/aws/smithy-go/rand"
- )
- // ComputeDelay computes delay between waiter attempts. The function takes in a current attempt count,
- // minimum delay, maximum delay, and remaining wait time for waiter as input. The inputs minDelay and maxDelay
- // must always be greater than 0, along with minDelay lesser than or equal to maxDelay.
- //
- // Returns the computed delay and if next attempt count is possible within the given input time constraints.
- // Note that the zeroth attempt results in no delay.
- func ComputeDelay(attempt int64, minDelay, maxDelay, remainingTime time.Duration) (delay time.Duration, err error) {
- // zeroth attempt, no delay
- if attempt <= 0 {
- return 0, nil
- }
- // remainingTime is zero or less, no delay
- if remainingTime <= 0 {
- return 0, nil
- }
- // validate min delay is greater than 0
- if minDelay == 0 {
- return 0, fmt.Errorf("minDelay must be greater than zero when computing Delay")
- }
- // validate max delay is greater than 0
- if maxDelay == 0 {
- return 0, fmt.Errorf("maxDelay must be greater than zero when computing Delay")
- }
- // Get attempt ceiling to prevent integer overflow.
- attemptCeiling := (math.Log(float64(maxDelay/minDelay)) / math.Log(2)) + 1
- if attempt > int64(attemptCeiling) {
- delay = maxDelay
- } else {
- // Compute exponential delay based on attempt.
- ri := 1 << uint64(attempt-1)
- // compute delay
- delay = minDelay * time.Duration(ri)
- }
- if delay != minDelay {
- // randomize to get jitter between min delay and delay value
- d, err := rand.CryptoRandInt63n(int64(delay - minDelay))
- if err != nil {
- return 0, fmt.Errorf("error computing retry jitter, %w", err)
- }
- delay = time.Duration(d) + minDelay
- }
- // check if this is the last attempt possible and compute delay accordingly
- if remainingTime-delay <= minDelay {
- delay = remainingTime - minDelay
- }
- return delay, nil
- }
|