added retry_after option to the retries plugin

This commit is contained in:
HoneyryderChuck 2020-02-10 00:09:50 +00:00
parent 46e8f57868
commit 98cce7df65
2 changed files with 61 additions and 2 deletions

View File

@ -25,6 +25,17 @@ module HTTPX
def self.extra_options(options)
Class.new(options.class) do
# number of seconds after which one can retry the request
def_option(:retry_after) do |num|
# return early if callable
return num if num.respond_to?(:call)
num = Integer(num)
raise Error, ":retry_after must be positive" unless num.positive?
num
end
def_option(:max_retries) do |num|
num = Integer(num)
raise Error, ":max_retries must be positive" unless num.positive?
@ -63,8 +74,7 @@ module HTTPX
log { "failed to get response, #{request.retries} tries to go..." }
request.transition(:idle)
connection = find_connection(request, connections, options)
connection.send(request)
set_request_timeout(connection, request, options)
__retry_request(connection, request, options)
return
end
response
@ -77,6 +87,23 @@ module HTTPX
def __retryable_error?(ex)
RETRYABLE_ERRORS.any? { |klass| ex.is_a?(klass) }
end
def __retry_request(connection, request, options)
retry_after = options.retry_after
unless retry_after
connection.send(request)
set_request_timeout(connection, request, options)
return
end
retry_after = retry_after.call(request) if retry_after.respond_to?(:call)
log { "retrying after #{retry_after} secs..." }
pool.after(retry_after) do
log { "retrying!!" }
connection.send(request)
set_request_timeout(connection, request, options)
end
end
end
module RequestMethods

View File

@ -46,6 +46,38 @@ module Requests
assert retries_session.calls.zero?, "expect request not to be retried (it was, #{retries_session.calls} times)"
end
def test_plugin_retries_retry_after
before_time = Process.clock_gettime(Process::CLOCK_MONOTONIC, :second)
retries_session = HTTPX
.plugin(RequestInspector)
.plugin(:retries, retry_after: 2)
.timeout(total_timeout: 3)
.max_retries(1)
retries_response = retries_session.get(build_uri("/delay/10"))
after_time = Process.clock_gettime(Process::CLOCK_MONOTONIC, :second)
total_time = after_time - before_time
assert retries_response.is_a?(HTTPX::ErrorResponse)
assert_in_delta 3 + 2 + 3, total_time, 1, "request didn't take as expected to retry (#{total_time} secs)"
end
def test_plugin_retries_retry_after_callable
retries = 0
exponential = ->(_) { (retries += 1) * 2 }
before_time = Process.clock_gettime(Process::CLOCK_MONOTONIC, :second)
retries_session = HTTPX
.plugin(RequestInspector)
.plugin(:retries, retry_after: exponential)
.timeout(total_timeout: 3)
.max_retries(2)
retries_response = retries_session.get(build_uri("/delay/10"))
after_time = Process.clock_gettime(Process::CLOCK_MONOTONIC, :second)
total_time = after_time - before_time
assert retries_response.is_a?(HTTPX::ErrorResponse)
assert_in_delta 3 + 2 + 3 + 4 + 3, total_time, 1, "request didn't take as expected to retry (#{total_time} secs)"
end
module RequestInspector
module InstanceMethods
attr_reader :calls