Faraday: How to use retry with POST method

Created on 12 Mar 2018  ·  3Comments  ·  Source: lostisland/faraday

Basic Info

  • Faraday Version:
    faraday (0.11.0)
    faraday_middleware (0.11.0.1)
    faraday_middleware-aws-signers-v4 (0.1.5)

  • Ruby Version:
    ruby 2.3.0p0 (2015-12-25 revision 53290) [x86_64-darwin15]

Issue description

I have an interface accessing some api, was using a Faraday connection with get method and setting a retry, and everything was working fine until I changed my method to post then the retry stopped working I googled a bit so I understood that the post is not included in the

IDEMPOTENT_METHODS = [:delete, :get, :head, :options, :put]

ref: https://github.com/lostisland/faraday/pull/437/files
and I have to use retry_if if I would like to retry the POST but didn't find a documentation dor retry_if.

So my connection looks like this:

    def my_connection(my_api_endpoint)
      Faraday.new(url: my_api_endpoint) do |faraday|
        faraday.request  :retry, max: 5, exceptions:
          [BadRequest, NotFound, ServerError, Faraday::Error::ConnectionFailed]
         faraday.response :logger
         faraday.adapter  Faraday.default_adapter
         faraday.options[:open_timeout] = 10
      end
    end

and calling it this way:

  res = my_connection(my_api_endpoint).post do |req|
    req.headers['Content-Type'] = 'application/json'
    req.options.timeout = 25
    req.body = body.to_json
  end

Any help will be very welcome.

Most helpful comment

Thanks for the feedback @yusefu and sorry for the TypeError.
I think the issue is that @connections should be a hash, not an array, my bad!

@connections ||= {}

Anyway, happy to know your issue is now solved 👍!

All 3 comments

Hi @yusefu, apologies for the lack of documentation, this is something we're trying to address in v1.0.
In the meantime, let me help with your issue. Basically the retry_if is an option you can pass exactly how you pass max: 5, exceptions: [BadRequest, NotFound, ServerError, Faraday::Error::ConnectionFailed]. The only difference is that retry_if must be a function (either a lambda or a proc.
If you're unfamiliar with those, I would suggest to go with a proc, which can be instantiated with Proc.new { ... } or with the multi-line Proc.new do ... end.

So if you want to use retry_if your example would become something like:

def my_connection(my_api_endpoint)
  # This is optional, I've added the @connections memoized variable to avoid
  # re-creating the connection every time. Not sure it's applicable to your case
  # but consider it as it might improve performances
  @connections ||= []
  @connections[my_api_endpoint] ||= Faraday.new(url: my_api_endpoint) do |faraday|
    faraday.request  :retry, max: 5, exceptions:
      [BadRequest, NotFound, ServerError, Faraday::Error::ConnectionFailed],
      retry_if: Proc.new do |env, exception|
        # your implementation goes here...
      end
     faraday.response :logger
     faraday.adapter  Faraday.default_adapter
     faraday.options[:open_timeout] = 10
  end
end

However, if your only aim is to add :post to the list of retry methods, you can also use the methods option added on that PR you linked:

def my_connection(my_api_endpoint)
  # This is optional, I've added the @connections memoized variable to avoid
  # re-creating the connection every time. Not sure it's applicable to your case
  # but consider it as it might improve performances
  @connections ||= []
  @connections[my_api_endpoint] ||= Faraday.new(url: my_api_endpoint) do |faraday|
    faraday.request  :retry, max: 5, exceptions:
      [BadRequest, NotFound, ServerError, Faraday::Error::ConnectionFailed],
      methods: Faraday::Request::Retry::IDEMPOTENT_METHODS + [:post]
     faraday.response :logger
     faraday.adapter  Faraday.default_adapter
     faraday.options[:open_timeout] = 10
  end
end

Please let me know if this helps 😄

The connections instance gave a TypeError.

expected MyAPI::BadRequest, got #<TypeError: {:req=>{}, :res=>nil, :headers=>nil, :reason_phrase=>nil}> with backtrace:

But with the simple add of post to IDEMPOTENT_METHODS the retry is now possible.
Thank you very much @iMacTia 🙏 it did work.

Thanks for the feedback @yusefu and sorry for the TypeError.
I think the issue is that @connections should be a hash, not an array, my bad!

@connections ||= {}

Anyway, happy to know your issue is now solved 👍!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

aleksb86 picture aleksb86  ·  3Comments

ryanbyon picture ryanbyon  ·  3Comments

luizkowalski picture luizkowalski  ·  3Comments

subvertallchris picture subvertallchris  ·  5Comments

ioquatix picture ioquatix  ·  4Comments