github.com/celestiaorg/celestia-node@v0.15.0-beta.1/das/backoff.go (about)

     1  package das
     2  
     3  import (
     4  	"time"
     5  )
     6  
     7  var (
     8  	// first retry attempt should happen after defaultBackoffInitialInterval
     9  	defaultBackoffInitialInterval = time.Minute
    10  	// next retry attempt will happen with delay of previous one multiplied by defaultBackoffMultiplier
    11  	defaultBackoffMultiplier = 4
    12  	// after defaultBackoffMaxRetryCount amount of attempts retry backoff interval will stop growing
    13  	// and each retry attempt will produce WARN log
    14  	defaultBackoffMaxRetryCount = 4
    15  )
    16  
    17  // retryStrategy defines a backoff for retries.
    18  type retryStrategy struct {
    19  	// attempts delays will follow durations stored in retryIntervals
    20  	retryIntervals []time.Duration
    21  }
    22  
    23  // newRetryStrategy creates and initializes a new retry backoff.
    24  func newRetryStrategy(retryIntervals []time.Duration) retryStrategy {
    25  	return retryStrategy{retryIntervals: retryIntervals}
    26  }
    27  
    28  // nextRetry creates a retry attempt with a backoff delay based on the retry backoff.
    29  // It takes the number of retry attempts and the time of the last attempt as inputs and returns a
    30  // retry instance and a boolean value indicating whether the retries amount have exceeded.
    31  func (s retryStrategy) nextRetry(lastRetry retryAttempt, lastAttempt time.Time,
    32  ) (retry retryAttempt, retriesExceeded bool) {
    33  	lastRetry.count++
    34  
    35  	if len(s.retryIntervals) == 0 {
    36  		return lastRetry, false
    37  	}
    38  
    39  	if lastRetry.count > len(s.retryIntervals) {
    40  		// try count exceeded backoff try limit
    41  		lastRetry.after = lastAttempt.Add(s.retryIntervals[len(s.retryIntervals)-1])
    42  		return lastRetry, true
    43  	}
    44  
    45  	lastRetry.after = lastAttempt.Add(s.retryIntervals[lastRetry.count-1])
    46  	return lastRetry, false
    47  }
    48  
    49  // exponentialBackoff generates an array of time.Duration values using an exponential growth
    50  // multiplier.
    51  func exponentialBackoff(baseInterval time.Duration, multiplier, amount int) []time.Duration {
    52  	backoff := make([]time.Duration, 0, amount)
    53  	next := baseInterval
    54  	for i := 0; i < amount; i++ {
    55  		backoff = append(backoff, next)
    56  		next *= time.Duration(multiplier)
    57  	}
    58  	return backoff
    59  }