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]
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.
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 👍!
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!Anyway, happy to know your issue is now solved 👍!