Search code examples
ruby-on-railsrails-activejob

do Rails Active Job support backoff retry strategies?


Does Rails ActiveJob support below retry strategies ?

  • Linear Backoff

    Linear backoff involves waiting for a progressively increasing fixed interval between retry attempts.

  • Linear Jitter Backoff

    Linear jitter backoff modifies the linear backoff strategy by introducing randomness to the retry intervals. This strategy still increases the delay linearly but adds a random "jitter" to each interval.

  • Exponential Backoff

    Exponential backoff involves increasing the delay between retries exponentially. The interval might start at 1 second, then increase to 2 seconds, 4 seconds, 8 seconds, and so on, typically up to a maximum delay. This approach is more aggressive in spacing out retries than linear backoff.

  • Exponential Jitter Backoff

    Exponential jitter backoff combines exponential backoff with randomness. After each retry, the backoff interval is exponentially increased, and then a random jitter is applied. The jitter can be either additive (adding a random amount to the exponential delay) or multiplicative (multiplying the exponential delay by a random factor).


Solution

  • You can create any strategy you need by passing a proc as a :wait option:

    # Linear Backoff
    retry_on Timeout::Error, wait: ->(executions) { executions * 10 }
    
    # Linear Jitter Backoff
    retry_on Timeout::Error, wait: ->(executions) { 
      seconds = executions * 10
      jitter = 0.3
      seconds + seconds * rand * jitter
    }
    
    # Exponential Backoff
    retry_on Timeout::Error, wait: ->(executions) { 2 ** executions }
    
    # Exponential Jitter Backoff
    retry_on Timeout::Error, wait: ->(executions) { 
      seconds = 2 ** executions
      jitter = 0.3
      seconds + seconds * rand * jitter
    }
    

    Note that there is a separate :jitter option which does not apply when :wait is a proc.

    :wait - Re-enqueues the job with a delay specified either in seconds (default: 3 seconds), as a computing proc that takes the number of executions so far as an argument, or as a symbol reference of :polynomially_longer, which applies the wait algorithm of ((executions**4) + (Kernel.rand * (executions**4) * jitter)) + 2 (first wait ~3s, then ~18s, then ~83s, etc)

    https://api.rubyonrails.org/v7.1.3.4/classes/ActiveJob/Exceptions/ClassMethods.html#method-i-retry_on