job の内部でネットワークエラーを拾うケースでは、定間隔より exponential backoff でリトライしたいなぁと考え調べた。
ActiveJob::Exceptions#retry_on
で定義されている。
def retry_on(*exceptions, wait: 3.seconds, attempts: 5, queue: nil, priority: nil, jitter: JITTER_DEFAULT) rescue_from(*exceptions) do |error| executions = executions_for(exceptions) if attempts == :unlimited || executions < attempts retry_job wait: determine_delay(seconds_or_duration_or_algorithm: wait, executions: executions, jitter: jitter), queue: queue, priority: priority, error: error else if block_given? instrument :retry_stopped, error: error do yield self, error end else instrument :retry_stopped, error: error raise error end end end end
rails/exceptions.rb at v7.0.4 · rails/rails · GitHub
間隔の決定は同クラスの #determine_delay
内で行っている。
def determine_delay(seconds_or_duration_or_algorithm:, executions:, jitter: JITTER_DEFAULT) jitter = jitter == JITTER_DEFAULT ? self.class.retry_jitter : (jitter || 0.0) case seconds_or_duration_or_algorithm when :exponentially_longer delay = executions**4 delay_jitter = determine_jitter_for_delay(delay, jitter) delay + delay_jitter + 2 when ActiveSupport::Duration, Integer delay = seconds_or_duration_or_algorithm.to_i delay_jitter = determine_jitter_for_delay(delay, jitter) delay + delay_jitter when Proc algorithm = seconds_or_duration_or_algorithm algorithm.call(executions) else raise "Couldn't determine a delay based on #{seconds_or_duration_or_algorithm.inspect}" end end
rails/exceptions.rb at v7.0.4 · rails/rails · GitHub
ということで wait
に ActiveSupport::Duration
(1.second
など)を渡すと jitter はあるものの定間隔でリトライする。 wait
に :exponentially_longer
を渡せば exponential backoff となる。