Catches exceptions and retries each request a limited number of times.
By default, it retries 2 times and handles only timeout exceptions. It can be configured with an arbitrary number of retries, a list of exceptions to handle, a retry interval, a percentage of randomness to add to the retry interval, and a backoff factor.
Examples
Faraday.new do |conn| conn.request :retry, max: 2, interval: 0.05, interval_randomness: 0.5, backoff_factor: 2 exceptions: [CustomException, 'Timeout::Error'] conn.adapter ... end
This example will result in a first interval that is random between 0.05 and 0.075 and a second interval that is random between 0.1 and 0.15
Public: Initialize middleware
Options: max - Maximum number of retries (default: 2) interval - Pause in seconds between retries (default: 0) interval_randomness - The maximum random interval amount expressed
as a float between 0 and 1 to use in addition to the interval. (default: 0)
backoff_factor - The amount to multiple each successive retry's
interval amount by in order to provide backoff (default: 1)
exceptions - The list of exceptions to handle. Exceptions can be
given as Class, Module, or String. (default: [Errno::ETIMEDOUT, Timeout::Error, Error::TimeoutError])
# File lib/faraday/request/retry.rb, line 69 def initialize(app, options = nil) super(app) @options = Options.from(options) @errmatch = build_exception_matcher(@options.exceptions) end
Private: construct an exception matcher object.
An exception matcher for the rescue clause can usually be any object that responds to `===`, but for Ruby 1.8 it has to be a Class or Module.
# File lib/faraday/request/retry.rb, line 102 def build_exception_matcher(exceptions) matcher = Module.new (class << matcher; self; end).class_eval do define_method(:===) do |error| exceptions.any? do |ex| if ex.is_a? Module error.is_a? ex else error.class.to_s == ex.to_s end end end end matcher end
# File lib/faraday/request/retry.rb, line 82 def call(env) retries = @options.max request_body = env[:body] begin env[:body] = request_body # after failure env[:body] is set to the response body @app.call(env) rescue @errmatch if retries > 0 retries -= 1 sleep sleep_amount(retries + 1) retry end raise end end
# File lib/faraday/request/retry.rb, line 75 def sleep_amount(retries) retry_index = @options.max - retries current_interval = @options.interval * (@options.backoff_factor ** retry_index) random_interval = rand * @options.interval_randomness.to_f * @options.interval current_interval + random_interval end