-
Notifications
You must be signed in to change notification settings - Fork 31
Open
Description
Basic Info
- Faraday Version: 1.7.1 (and also main branch at fdf797b)
- Ruby Version: 2.7.4
Issue description
The retry count middleware does not wait for completed requests when in parallel, hence retries are not issued.
Steps to reproduce
#!/usr/bin/env ruby
# frozen_string_literal: true
require "bundler/inline"
gemfile do
source "https://rubygems.org"
gem "faraday"
gem "typhoeus"
end
count = 0
expected = 5
faraday = Faraday.new do |conn|
retry_options = {
max: expected,
interval: 0.1,
retry_statuses: [503],
retry_block: proc { count += 1 }
}
conn.request :retry, **retry_options
conn.adapter :typhoeus
end
faraday.in_parallel do
faraday.get("https://httpbin.org/status/503")
end
exit 0 if count == expected
warn "Retried #{count} times, expected #{expected}"
exit 1Fix
Note that I already found a fix working locally for typhoeus, I would just like to know if that's a bug for you and I spend my time wisely making it work in every cases! (I think the tricky part will concern chaining with the raise middleware)
Here's a working patch for the precise reproduction above:
diff --git a/lib/faraday/request/retry.rb b/lib/faraday/request/retry.rb
index 3ba50b7..460b683 100644
--- a/lib/faraday/request/retry.rb
+++ b/lib/faraday/request/retry.rb
@@ -145,10 +145,29 @@ module Faraday
begin
# after failure env[:body] is set to the response body
env[:body] = request_body
- @app.call(env).tap do |resp|
+ # TODO: distinguish the parallel and usual pipeline for this.
+ @app.call(env).on_complete do |resp|
+ if !resp.status
+ raise "bug!"
+ end
if @options.retry_statuses.include?(resp.status)
raise Faraday::RetriableResponse.new(nil, resp)
end
+ rescue @errmatch => e
+ # TODO: dry...
+ if retries.positive? && retry_request?(env, e)
+ retries -= 1
+ rewind_files(request_body)
+ @options.retry_block.call(env, @options, retries, e)
+ if (sleep_amount = calculate_sleep_amount(retries + 1, env))
+ sleep sleep_amount
+ retry
+ end
+
+ raise unless e.is_a?(Faraday::RetriableResponse)
+
+ e.response
+ end
end
rescue @errmatch => e
if retries.positive? && retry_request?(env, e)If you're in I should be able to get that done within 2 weeks
Bonus
Note that the instrumentation middleware has basically the same issue, I can fix it with
diff --git a/lib/faraday/request/instrumentation.rb b/lib/faraday/request/instrumentation.rb
index c03ba1e..84822d6 100644
--- a/lib/faraday/request/instrumentation.rb
+++ b/lib/faraday/request/instrumentation.rb
@@ -44,10 +44,13 @@ module Faraday
end
# @param env [Faraday::Env]
- def call(env)
- @instrumenter.instrument(@name, env) do
- @app.call(env)
- end
+ def on_request(env)
+ @instrumenter.start(@name, env)
+ end
+
+ # @param env [Faraday::Env]
+ def on_complete(env)
+ @instrumenter.finish(@name, env)
end
end
endOne issue though, the time (ends - starts) would be wrong, and I see that faraday does not add the request time to env data..
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels