class Faraday::Retry::Middleware

IMPORTANT: Remember to call ‘@app.call(env)` or `super` to not interrupt the middleware chain!
(see “retry” middleware: github.com/lostisland/faraday/blob/main/lib/faraday/request/retry.rb#L142).
You may need to in case you need to “wrap” the request or need more control
This already calls on_request and on_complete, so you normally don’t need to override it.
* call(env) - the main middleware invocation method.
* initialize(app, options = {}) - the initializer method
Optionally, you can also override the following methods from Faraday::Middleware
* on_complete - called when the response is being processed
* on_request - called when the request is being prepared
Your middleware can implement any of the following methods:
This class provides the main implementation for your middleware.

def build_exception_matcher(exceptions)

Returns:
  • (Module) - an exception matcher

Other tags:
    Api: - private

Parameters:
  • exceptions (Array) --
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
          Object.const_defined?(ex.to_s) && error.is_a?(Object.const_get(ex.to_s))
        end
      end
    end
  end
  matcher
end

def calculate_rate_limit_reset(env)

https://www.ietf.org/archive/id/draft-ietf-httpapi-ratelimit-headers-05.html#name-fields-definition
RFC for RateLimit Header Fields for HTTP:
def calculate_rate_limit_reset(env)
  reset_header = @options.rate_limit_reset_header || 'RateLimit-Reset'
  parse_retry_header(env, reset_header)
end

def calculate_retry_after(env)

https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Retry-After
MDN spec for Retry-After header:
def calculate_retry_after(env)
  retry_header = @options.rate_limit_retry_header || 'Retry-After'
  parse_retry_header(env, retry_header)
end

def calculate_retry_interval(retries)

def calculate_retry_interval(retries)
  retry_index = @options.max - retries
  current_interval = @options.interval *
                     (@options.backoff_factor**retry_index)
  current_interval = [current_interval, @options.max_interval].min
  random_interval = rand * @options.interval_randomness.to_f *
                    @options.interval
  current_interval + random_interval
end

def calculate_sleep_amount(retries, env)

def calculate_sleep_amount(retries, env)
  retry_after = [calculate_retry_after(env), calculate_rate_limit_reset(env)].compact.max
  retry_interval = calculate_retry_interval(retries)
  return if retry_after && retry_after > @options.max_interval
  if retry_after && retry_after >= retry_interval
    retry_after
  else
    retry_interval
  end
end

def call(env)

Parameters:
  • env (Faraday::Env) --
def call(env)
  retries = @options.max
  request_body = env[:body]
  with_retries(env: env, options: @options, retries: retries, body: request_body, errmatch: @errmatch) do
    # after failure env[:body] is set to the response body
    env[:body] = request_body
    @app.call(env).tap do |resp|
      raise Faraday::RetriableResponse.new(nil, resp) if @options.retry_statuses.include?(resp.status)
    end
  end
end

def initialize(app, options = nil)

Options Hash: (**options)
  • :exhausted_retries_block (Block) -- block will receive
  • :header_parser_block (Block) -- block that will receive
  • :retry_statuses (Array) -- Array of Integer HTTP status
  • :retry_block (Block) -- block that is executed before
  • :retry_if (Block) -- block that will receive
  • :methods (Array) -- the idempotent HTTP methods
  • :exceptions (Array) -- [ Errno::ETIMEDOUT,
  • :backoff_factor (Integer) -- The amount to multiply
  • :max_interval (Integer) -- An upper limit
  • :interval_randomness (Integer) -- The maximum random
  • :interval (Integer) -- Pause in seconds between retries
  • :max (Integer) -- Maximum number of retries

Parameters:
  • options (Hash) --
  • app (#call) --
def initialize(app, options = nil)
  super(app)
  @options = Options.from(options)
  @errmatch = build_exception_matcher(@options.exceptions)
end

def parse_retry_header(env, header)

def parse_retry_header(env, header)
  response_headers = env[:response_headers]
  return unless response_headers
  retry_after_value = env[:response_headers][header]
  if @options.header_parser_block
    @options.header_parser_block.call(retry_after_value)
  else
    # Try to parse date from the header value
    begin
      datetime = DateTime.rfc2822(retry_after_value)
      datetime.to_time - Time.now.utc
    rescue ArgumentError
      retry_after_value.to_f
    end
  end
end

def retry_request?(env, exception)

def retry_request?(env, exception)
  @options.methods.include?(env[:method]) ||
    @options.retry_if.call(env, exception)
end

def rewind_files(body)

def rewind_files(body)
  return unless defined?(Faraday::UploadIO)
  return unless body.is_a?(Hash)
  body.each do |_, value|
    value.rewind if value.is_a?(Faraday::UploadIO)
  end
end