mirror of
https://github.com/HoneyryderChuck/httpx.git
synced 2025-08-10 00:01:27 -04:00
changed timeout so it relies on a loop timeout and a global timeout; both can be disabled
This commit is contained in:
parent
8797eebbf2
commit
65722a3b12
@ -42,8 +42,8 @@ module HTTPX
|
||||
branch(**options).request(verb, uri)
|
||||
end
|
||||
|
||||
def timeout(klass, **options)
|
||||
branch(timeout: Timeout.by(klass, **options))
|
||||
def timeout(**args)
|
||||
branch(timeout: args)
|
||||
end
|
||||
|
||||
def headers(headers)
|
||||
|
@ -44,7 +44,7 @@ module HTTPX
|
||||
:ssl => { alpn_protocols: %w[h2 http/1.1] },
|
||||
:http2_settings => { settings_enable_push: 0 },
|
||||
:fallback_protocol => "http/1.1",
|
||||
:timeout => Timeout.by(:per_operation),
|
||||
:timeout => Timeout.new,
|
||||
:headers => {},
|
||||
:max_concurrent_requests => MAX_CONCURRENT_REQUESTS,
|
||||
:max_retries => MAX_RETRIES,
|
||||
@ -65,8 +65,8 @@ module HTTPX
|
||||
self.headers.merge(headers)
|
||||
end
|
||||
|
||||
def_option(:timeout) do |type, opts|
|
||||
self.timeout = Timeout.by(type, opts)
|
||||
def_option(:timeout) do |opts|
|
||||
self.timeout = Timeout.new(opts)
|
||||
end
|
||||
|
||||
def_option(:max_concurrent_requests) do |num|
|
||||
@ -98,7 +98,7 @@ module HTTPX
|
||||
|
||||
merged = h1.merge(h2) do |k, v1, v2|
|
||||
case k
|
||||
when :headers, :ssl, :http2_settings
|
||||
when :headers, :ssl, :http2_settings, :timeout
|
||||
v1.merge(v2)
|
||||
else
|
||||
v2
|
||||
|
@ -1,29 +1,70 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require "timeout"
|
||||
|
||||
module HTTPX
|
||||
module Timeout
|
||||
class << self
|
||||
def by(type, **opts)
|
||||
case type
|
||||
when :null
|
||||
Null.new(opts)
|
||||
when :per_operation
|
||||
PerOperation.new(opts)
|
||||
when :global
|
||||
Global.new(opts)
|
||||
when Null, Global, PerOperation
|
||||
type.new(opts)
|
||||
when Hash # default way
|
||||
PerOperation.new(type)
|
||||
else
|
||||
raise "#{type}: unrecognized timeout option"
|
||||
end
|
||||
end
|
||||
class Timeout
|
||||
LOOP_TIMEOUT = 5
|
||||
|
||||
def self.new(opts = {})
|
||||
return opts if opts.is_a?(Timeout)
|
||||
super
|
||||
end
|
||||
|
||||
def initialize(loop_timeout: 5, total_timeout: nil)
|
||||
@loop_timeout = loop_timeout
|
||||
@total_timeout = total_timeout
|
||||
reset_counter
|
||||
end
|
||||
|
||||
def timeout
|
||||
@loop_timeout || @total_timeout
|
||||
ensure
|
||||
log_time
|
||||
end
|
||||
|
||||
def ==(other)
|
||||
if other.is_a?(Timeout)
|
||||
@loop_timeout == other.instance_variable_get(:@loop_timeout) &&
|
||||
@total_timeout == other.instance_variable_get(:@total_timeout)
|
||||
else
|
||||
super
|
||||
end
|
||||
end
|
||||
|
||||
def merge(other)
|
||||
case other
|
||||
when Hash
|
||||
timeout = Timeout.new(other)
|
||||
merge(timeout)
|
||||
when Timeout
|
||||
loop_timeout = other.instance_variable_get(:@loop_timeout) || @loop_timeout
|
||||
total_timeout = other.instance_variable_get(:@total_timeout) || @total_timeout
|
||||
Timeout.new(loop_timeout: loop_timeout, total_timeout: total_timeout)
|
||||
else
|
||||
raise ArgumentError, "can't merge with #{other.class}"
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def reset_counter
|
||||
@time_left = @total_timeout
|
||||
end
|
||||
|
||||
def reset_timer
|
||||
@started = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
||||
end
|
||||
|
||||
def log_time
|
||||
return unless @time_left
|
||||
return reset_timer unless @started
|
||||
@time_left -= (Process.clock_gettime(Process::CLOCK_MONOTONIC) - @started)
|
||||
if @time_left <= 0
|
||||
raise TimeoutError, "Timed out after #{@total_timeout} seconds"
|
||||
end
|
||||
|
||||
reset_timer
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
require "httpx/timeout/null"
|
||||
require "httpx/timeout/per_operation"
|
||||
require "httpx/timeout/global"
|
||||
|
@ -1,50 +0,0 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require "timeout"
|
||||
|
||||
module HTTPX::Timeout
|
||||
class Global < PerOperation
|
||||
TOTAL_TIMEOUT = 15
|
||||
|
||||
attr_reader :total_timeout
|
||||
|
||||
def initialize(total_timeout: TOTAL_TIMEOUT)
|
||||
@total_timeout = total_timeout
|
||||
reset_counter
|
||||
@running = false
|
||||
end
|
||||
|
||||
def ==(other)
|
||||
other.is_a?(Global) &&
|
||||
@total_timeout == other.total_timeout
|
||||
end
|
||||
|
||||
def timeout
|
||||
unless @running
|
||||
reset_timer
|
||||
@running = true
|
||||
end
|
||||
log_time
|
||||
@time_left
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def reset_counter
|
||||
@time_left = @total_timeout
|
||||
end
|
||||
|
||||
def reset_timer
|
||||
@started = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
||||
end
|
||||
|
||||
def log_time
|
||||
@time_left -= (Process.clock_gettime(Process::CLOCK_MONOTONIC) - @started)
|
||||
if @time_left <= 0
|
||||
raise HTTPX::TimeoutError, "Timed out after using the allocated #{@total_timeout} seconds"
|
||||
end
|
||||
|
||||
reset_timer
|
||||
end
|
||||
end
|
||||
end
|
@ -1,16 +0,0 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module HTTPX::Timeout
|
||||
class Null
|
||||
def initialize(**)
|
||||
end
|
||||
|
||||
def ==(other)
|
||||
other.is_a?(Null)
|
||||
end
|
||||
|
||||
def timeout
|
||||
nil
|
||||
end
|
||||
end
|
||||
end
|
@ -1,32 +0,0 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require "timeout"
|
||||
|
||||
module HTTPX::Timeout
|
||||
class PerOperation < Null
|
||||
OPERATION_TIMEOUT = 5
|
||||
CONNECT_TIMEOUT = 5
|
||||
|
||||
attr_reader :connect_timeout, :operation_timeout
|
||||
|
||||
def initialize(connect: CONNECT_TIMEOUT,
|
||||
operation: OPERATION_TIMEOUT)
|
||||
@connect_timeout = connect
|
||||
@operation_timeout = operation
|
||||
@timeout = @connect_timeout
|
||||
end
|
||||
|
||||
def timeout
|
||||
timeout = @timeout
|
||||
@timeout = @operation_timeout
|
||||
timeout
|
||||
end
|
||||
|
||||
def ==(other)
|
||||
other.is_a?(PerOperation) &&
|
||||
@connect_timeout == other.connect_timeout &&
|
||||
@operation_timeout == other.operation_timeout
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -53,7 +53,6 @@ class OptionsSpec < Minitest::Test
|
||||
:ssl => {:foo => "bar"},
|
||||
)
|
||||
|
||||
|
||||
assert foo.merge(bar).to_hash == {
|
||||
:io => ENV.key?("HTTPX_DEBUG") ? $stderr : nil,
|
||||
:debug => nil,
|
||||
@ -65,7 +64,7 @@ class OptionsSpec < Minitest::Test
|
||||
:window_size => 16_384,
|
||||
:body_threshold_size => 114_688,
|
||||
:form => {:bar => "bar"},
|
||||
:timeout => Timeout::PerOperation.new,
|
||||
:timeout => Timeout.new,
|
||||
:ssl => {:foo => "bar", :alpn_protocols => %w[h2 http/1.1] },
|
||||
:http2_settings => { :settings_enable_push => 0 },
|
||||
:fallback_protocol => "http/1.1",
|
||||
|
Loading…
x
Reference in New Issue
Block a user