Merge branch 'retries' into 'master'

Retries

Closes #17

See merge request honeyryderchuck/httpx!23
This commit is contained in:
HoneyryderChuck 2018-06-11 17:56:46 +00:00
commit e666dfb85d
4 changed files with 106 additions and 0 deletions

View File

@ -0,0 +1,52 @@
# frozen_string_literal: true
module HTTPX
module Plugins
module Retries
MAX_RETRIES = 3
IDEMPOTENT_METHODS = %i[get options head put delete].freeze
module InstanceMethods
def max_retries(n)
branch(default_options.with_max_retries(n.to_i))
end
private
def fetch_response(request)
response = super
if response.is_a?(ErrorResponse) &&
request.retries.positive? &&
IDEMPOTENT_METHODS.include?(request.verb)
request.retries -= 1
channel = find_channel(request)
channel.send(request)
return
end
response
end
end
module RequestMethods
attr_accessor :retries
def initialize(*args)
super
@retries = @options.max_retries || MAX_RETRIES
end
end
module OptionsMethods
def self.included(klass)
super
klass.def_option(:max_retries) do |num|
num = Integer(num)
raise Error, ":max_retries must be positive" unless num.positive?
num
end
end
end
end
register_plugin :retries, Retries
end
end

View File

@ -22,6 +22,7 @@ class HTTPTest < Minitest::Test
include Plugins::Cookies
include Plugins::Compression
include Plugins::H2C
include Plugins::Retries
private

View File

@ -20,6 +20,7 @@ class HTTPSTest < Minitest::Test
include Plugins::Cookies
include Plugins::Compression
include Plugins::PushPromise if OpenSSL::SSL::SSLContext.instance_methods.include?(:alpn_protocols)
include Plugins::Retries
private

View File

@ -0,0 +1,52 @@
# frozen_string_literal: true
module Requests
module Plugins
module Retries
def test_plugin_retries
no_retries_client = HTTPX.plugin(RequestInspector).timeout(total_timeout: 3)
no_retries_response = no_retries_client.get(build_uri("/delay/10"))
assert no_retries_response.is_a?(HTTPX::ErrorResponse)
assert no_retries_client.calls == 1, "expect request to be built 1 times (was #{no_retries_client.calls})"
retries_client = HTTPX
.plugin(RequestInspector)
.plugin(:retries)
.timeout(total_timeout: 3)
retries_response = retries_client.get(build_uri("/delay/10"))
assert retries_response.is_a?(HTTPX::ErrorResponse)
# we're comparing against max-retries + 1, because the calls increment will happen
# also in the last call, where the request is not going to be retried.
assert retries_client.calls == 4, "expect request to be built 4 times (was #{retries_client.calls})"
end
def test_plugin_retries_max_retries
retries_client = HTTPX
.plugin(RequestInspector)
.plugin(:retries)
.timeout(total_timeout: 3)
.max_retries(2)
retries_response = retries_client.get(build_uri("/delay/10"))
assert retries_response.is_a?(HTTPX::ErrorResponse)
# we're comparing against max-retries + 1, because the calls increment will happen
# also in the last call, where the request is not going to be retried.
assert retries_client.calls == 3, "expect request to be built 3 times (was #{retries_client.calls})"
end
module RequestInspector
module InstanceMethods
attr_reader :calls
def initialize(*args)
super
@calls = 0
end
def fetch_response(*)
response = super
@calls += 1 if response
response
end
end
end
end
end
end