lostisland/faraday-retry

Can't seem to conditionally wait with a 429

jesseduffield opened this issue · 0 comments

Basic Version Info

Faraday Version: 2.9.0
Ruby Version: 3.2.2

Issue description

I'm using faraday in a background job via ActiveJob. I would like to conditionally sleep inline depending on how large the 429 retry-after header's value is. If the value is sufficiently large, I want to re-raise the error and have ActiveJob catch it and reschedule the job in the future, using the retry-after header from the exception.

But, I can't see how to tell faraday-retry that I want to re-raise an error. It seems that faraday will wait after the retry block anyway.

Actual behavior

error is not re-raised

Expected behavior

error is re-raised.

Steps to reproduce

I don't know of a way to easily reproduce because httpbin doesn't return a retry-after header, but here's the general idea:

#!/usr/bin/env ruby
# frozen_string_literal: true

require "bundler/inline"

gemfile do
  source "https://rubygems.org"

  gem "faraday"
  gem "faraday-retry"
end

retry_options = {
  max: 1,
  exceptions: Faraday::Retry::Middleware::DEFAULT_EXCEPTIONS + [Faraday::TooManyRequestsError],
  retry_block: ->(env:, options:, retry_count:, exception:, will_retry_in:) {
    if exception.is_a?(Faraday::TooManyRequestsError)
      retry_after = exception.response[:headers]["retry-after"].to_i
      if retry_after < 10
        sleep retry_after
      else
        # This will be caught at the top level and used to reschedule the job
        # in the future
        raise(exception)
      end
    end
  },
}
faraday = Faraday.new do |conn|
  conn.request :retry, **retry_options
end

faraday.get("https://httpbin.org/status/429")

Thanks