github.com/spi-ca/misc@v1.0.1/backoff/backoff.go (about)

     1  package backoff
     2  
     3  import (
     4  	"math"
     5  	"time"
     6  )
     7  
     8  // Algorithm defines a function that calculates a time.Duration based on
     9  // the given retry attempt number.
    10  type Algorithm func(attempt uint) time.Duration
    11  
    12  // Incremental creates a Algorithm that increments the initial duration
    13  // by the given increment for each attempt.
    14  func Incremental(initial, increment time.Duration) Algorithm {
    15  	return func(attempt uint) time.Duration {
    16  		return initial + (increment * time.Duration(attempt))
    17  	}
    18  }
    19  
    20  // Linear creates a Algorithm that linearly multiplies the factor
    21  // duration by the attempt number for each attempt.
    22  func Linear(factor time.Duration) Algorithm {
    23  	return func(attempt uint) time.Duration {
    24  		return factor * time.Duration(attempt)
    25  	}
    26  }
    27  
    28  // Exponential creates a Algorithm that multiplies the factor duration by
    29  // an exponentially increasing factor for each attempt, where the factor is
    30  // calculated as the given base raised to the attempt number.
    31  func Exponential(factor time.Duration, base float64) Algorithm {
    32  	return func(attempt uint) time.Duration {
    33  		return factor * time.Duration(math.Pow(base, float64(attempt)))
    34  	}
    35  }
    36  
    37  // BinaryExponential creates a Algorithm that multiplies the factor
    38  // duration by an exponentially increasing factor for each attempt, where the
    39  // factor is calculated as `2` raised to the attempt number (2^attempt).
    40  func BinaryExponential(factor time.Duration) Algorithm {
    41  	return Exponential(factor, 2)
    42  }
    43  
    44  // Fibonacci creates a Algorithm that multiplies the factor duration by
    45  // an increasing factor for each attempt, where the factor is the Nth number in
    46  // the Fibonacci sequence.
    47  func Fibonacci(factor time.Duration) Algorithm {
    48  	return func(attempt uint) time.Duration {
    49  		return factor * time.Duration(fibonacciNumber(attempt))
    50  	}
    51  }
    52  
    53  // fibonacciNumber calculates the Fibonacci sequence number for the given
    54  // sequence position.
    55  func fibonacciNumber(n uint) uint {
    56  	if 0 == n {
    57  		return 0
    58  	} else if 1 == n {
    59  		return 1
    60  	} else {
    61  		return fibonacciNumber(n-1) + fibonacciNumber(n-2)
    62  	}
    63  }