Class: Tenax::Retry::Backoff::DecorrelatedJitter
- Defined in:
- lib/tenax/retry/backoff/decorrelated_jitter.rb
Overview
Decorrelated jitter backoff (AWS-style).
delay = min(cap, random(base, previous_delay * 3)) On the first attempt (no previous_delay), delay = random(base, base * 3).
This is the recommended backoff for production retry against shared remote services. It avoids both the synchronization problem of plain exponential backoff and the "stuck low" problem of full jitter.
See: https://aws.amazon.com/blogs/architecture/exponential-backoff-and-jitter/
Instance Method Summary collapse
-
#delay_for(attempt, previous_delay: nil) ⇒ Float
Delay seconds in [base, cap].
-
#initialize(base:, cap:, random: Random.new) ⇒ DecorrelatedJitter
constructor
A new instance of DecorrelatedJitter.
Constructor Details
#initialize(base:, cap:, random: Random.new) ⇒ DecorrelatedJitter
Returns a new instance of DecorrelatedJitter.
30 31 32 33 34 35 36 37 38 39 |
# File 'lib/tenax/retry/backoff/decorrelated_jitter.rb', line 30 def initialize(base:, cap:, random: Random.new) raise ArgumentError, "base must be positive, got #{base}" if base <= 0 raise ArgumentError, "cap must be >= base, got base=#{base}, cap=#{cap}" if cap < base super() @base = base.to_f @cap = cap.to_f @random = random freeze end |
Instance Method Details
#delay_for(attempt, previous_delay: nil) ⇒ Float
Returns delay seconds in [base, cap].
44 45 46 47 48 49 50 51 52 53 54 55 56 |
# File 'lib/tenax/retry/backoff/decorrelated_jitter.rb', line 44 def delay_for(attempt, previous_delay: nil) raise ArgumentError, "attempt must be >= 1, got #{attempt}" if attempt < 1 # On the first retry, seed with `base` so the formula has a starting point. prev = previous_delay || @base upper = [prev * 3, @cap].min # If upper has fallen to base (or below — shouldn't happen but be defensive), # we just return base; no random range to draw from. return @base if upper <= @base @base + (@random.rand * (upper - @base)) end |