mirror of
https://github.com/lostisland/faraday.git
synced 2025-11-27 00:04:03 -05:00
improve Retry middleware, change to only handle timeouts
Also supercharge it with :max, :interval, and :exceptions options. Closes #158
This commit is contained in:
parent
98ba9137f6
commit
e8c98c4323
@ -1,5 +1,3 @@
|
|||||||
require 'timeout'
|
|
||||||
|
|
||||||
module Faraday
|
module Faraday
|
||||||
class Adapter
|
class Adapter
|
||||||
# Sends requests to a Rack app.
|
# Sends requests to a Rack app.
|
||||||
|
|||||||
@ -1,17 +1,34 @@
|
|||||||
module Faraday
|
module Faraday
|
||||||
class Request::Retry < Faraday::Middleware
|
class Request::Retry < Faraday::Middleware
|
||||||
def initialize(app, retries = 2)
|
def initialize(app, options = {})
|
||||||
@retries = retries
|
|
||||||
super(app)
|
super(app)
|
||||||
|
@retries, options = options, {} if options.is_a? Integer
|
||||||
|
@retries ||= options.fetch(:max, 2).to_i
|
||||||
|
@sleep = options.fetch(:interval, 0).to_f
|
||||||
|
to_handle = options.fetch(:exceptions) {
|
||||||
|
[Errno::ETIMEDOUT, 'Timeout::Error', Error::TimeoutError]
|
||||||
|
}
|
||||||
|
@errmatch = ExceptionMatcher.new Array(to_handle)
|
||||||
|
end
|
||||||
|
|
||||||
|
class ExceptionMatcher < Struct.new(:exceptions)
|
||||||
|
def ===(error)
|
||||||
|
exceptions.any? do |ex|
|
||||||
|
if ex.is_a? Module then error.is_a? ex
|
||||||
|
else error.class.to_s == ex.to_s
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def call(env)
|
def call(env)
|
||||||
retries = @retries
|
retries = @retries
|
||||||
begin
|
begin
|
||||||
@app.call(env)
|
@app.call(env)
|
||||||
rescue StandardError, Timeout::Error
|
rescue @errmatch
|
||||||
if retries > 0
|
if retries > 0
|
||||||
retries -= 1
|
retries -= 1
|
||||||
|
sleep @sleep if @sleep > 0
|
||||||
retry
|
retry
|
||||||
end
|
end
|
||||||
raise
|
raise
|
||||||
|
|||||||
@ -3,23 +3,60 @@ require File.expand_path(File.join(File.dirname(__FILE__), "..", "helper"))
|
|||||||
module Middleware
|
module Middleware
|
||||||
class RetryTest < Faraday::TestCase
|
class RetryTest < Faraday::TestCase
|
||||||
def setup
|
def setup
|
||||||
@stubs = Faraday::Adapter::Test::Stubs.new
|
@times_called = 0
|
||||||
@conn = Faraday.new do |b|
|
end
|
||||||
b.request :retry, 2
|
|
||||||
b.adapter :test, @stubs
|
def conn(*retry_args)
|
||||||
|
Faraday.new do |b|
|
||||||
|
b.request :retry, *retry_args
|
||||||
|
b.adapter :test do |stub|
|
||||||
|
stub.post('/unstable') {
|
||||||
|
@times_called += 1
|
||||||
|
@explode.call @times_called
|
||||||
|
}
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_retries
|
def test_unhandled_error
|
||||||
times_called = 0
|
@explode = lambda {|n| raise "boom!" }
|
||||||
|
assert_raise(RuntimeError) { conn.post("/unstable") }
|
||||||
|
assert_equal 1, @times_called
|
||||||
|
end
|
||||||
|
|
||||||
@stubs.post("/echo") do
|
def test_handled_error
|
||||||
times_called += 1
|
@explode = lambda {|n| raise Errno::ETIMEDOUT }
|
||||||
raise "Error occurred"
|
assert_raise(Errno::ETIMEDOUT) { conn.post("/unstable") }
|
||||||
end
|
assert_equal 3, @times_called
|
||||||
|
end
|
||||||
|
|
||||||
@conn.post("/echo") rescue nil
|
def test_legacy_max_retries
|
||||||
assert_equal times_called, 3
|
@explode = lambda {|n| raise Errno::ETIMEDOUT }
|
||||||
|
assert_raise(Errno::ETIMEDOUT) { conn(1).post("/unstable") }
|
||||||
|
assert_equal 2, @times_called
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_new_max_retries
|
||||||
|
@explode = lambda {|n| raise Errno::ETIMEDOUT }
|
||||||
|
assert_raise(Errno::ETIMEDOUT) { conn(:max => 3).post("/unstable") }
|
||||||
|
assert_equal 4, @times_called
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_interval
|
||||||
|
@explode = lambda {|n| raise Errno::ETIMEDOUT }
|
||||||
|
started = Time.now
|
||||||
|
assert_raise(Errno::ETIMEDOUT) {
|
||||||
|
conn(:max => 2, :interval => 0.1).post("/unstable")
|
||||||
|
}
|
||||||
|
assert_in_delta 0.2, Time.now - started, 0.02
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_custom_exceptions
|
||||||
|
@explode = lambda {|n| raise "boom!" }
|
||||||
|
assert_raise(RuntimeError) {
|
||||||
|
conn(:exceptions => StandardError).post("/unstable")
|
||||||
|
}
|
||||||
|
assert_equal 3, @times_called
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user