lib/httpx/plugins/retries.rb in httpx-0.6.5 vs lib/httpx/plugins/retries.rb in httpx-0.6.6

- old
+ new

@@ -23,18 +23,35 @@ Errno::EINVAL, Errno::ETIMEDOUT].freeze 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? num end def_option(:retry_change_requests) + + def_option(:retry_on) do |callback| + raise ":retry_on must be called with the response" unless callback.respond_to?(:call) && callback.method(:call).arity == 1 + + callback + end end.new(options).merge(max_retries: MAX_RETRIES) end module InstanceMethods def max_retries(n) @@ -43,20 +60,23 @@ private def fetch_response(request, connections, options) response = super + + retry_on = options.retry_on + if response.is_a?(ErrorResponse) && request.retries.positive? && __repeatable_request?(request, options) && - __retryable_error?(response.error) + __retryable_error?(response.error) && + (!retry_on || retry_on.call(response)) request.retries -= 1 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 end @@ -64,9 +84,26 @@ IDEMPOTENT_METHODS.include?(request.verb) || options.retry_change_requests end 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 attr_accessor :retries