httpx 1.2.6 → 1.4.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +1 -2
- data/doc/release_notes/1_3_0.md +18 -0
- data/doc/release_notes/1_3_1.md +17 -0
- data/doc/release_notes/1_3_2.md +6 -0
- data/doc/release_notes/1_3_3.md +5 -0
- data/doc/release_notes/1_3_4.md +6 -0
- data/doc/release_notes/1_4_0.md +43 -0
- data/doc/release_notes/1_4_1.md +19 -0
- data/doc/release_notes/1_4_2.md +20 -0
- data/doc/release_notes/1_4_3.md +11 -0
- data/doc/release_notes/1_4_4.md +14 -0
- data/lib/httpx/adapters/datadog.rb +56 -80
- data/lib/httpx/adapters/faraday.rb +5 -2
- data/lib/httpx/adapters/webmock.rb +24 -8
- data/lib/httpx/callbacks.rb +2 -7
- data/lib/httpx/chainable.rb +3 -1
- data/lib/httpx/connection/http1.rb +11 -7
- data/lib/httpx/connection/http2.rb +57 -34
- data/lib/httpx/connection.rb +270 -71
- data/lib/httpx/errors.rb +15 -4
- data/lib/httpx/io/ssl.rb +6 -3
- data/lib/httpx/io/tcp.rb +1 -1
- data/lib/httpx/io/unix.rb +1 -1
- data/lib/httpx/loggable.rb +17 -10
- data/lib/httpx/options.rb +30 -23
- data/lib/httpx/plugins/aws_sdk_authentication.rb +3 -0
- data/lib/httpx/plugins/aws_sigv4.rb +36 -17
- data/lib/httpx/plugins/callbacks.rb +13 -2
- data/lib/httpx/plugins/circuit_breaker.rb +11 -5
- data/lib/httpx/plugins/content_digest.rb +202 -0
- data/lib/httpx/plugins/cookies.rb +9 -6
- data/lib/httpx/plugins/digest_auth.rb +3 -0
- data/lib/httpx/plugins/expect.rb +10 -4
- data/lib/httpx/plugins/follow_redirects.rb +68 -33
- data/lib/httpx/plugins/grpc/grpc_encoding.rb +2 -0
- data/lib/httpx/plugins/grpc.rb +2 -2
- data/lib/httpx/plugins/h2c.rb +23 -20
- data/lib/httpx/plugins/internal_telemetry.rb +48 -1
- data/lib/httpx/plugins/oauth.rb +1 -1
- data/lib/httpx/plugins/persistent.rb +16 -0
- data/lib/httpx/plugins/proxy/http.rb +19 -16
- data/lib/httpx/plugins/proxy/socks4.rb +1 -1
- data/lib/httpx/plugins/proxy/socks5.rb +1 -1
- data/lib/httpx/plugins/proxy.rb +96 -85
- data/lib/httpx/plugins/retries.rb +28 -10
- data/lib/httpx/plugins/ssrf_filter.rb +4 -1
- data/lib/httpx/plugins/stream.rb +42 -18
- data/lib/httpx/plugins/upgrade.rb +5 -10
- data/lib/httpx/plugins/webdav.rb +6 -0
- data/lib/httpx/plugins/xml.rb +76 -0
- data/lib/httpx/pool.rb +73 -244
- data/lib/httpx/request/body.rb +50 -55
- data/lib/httpx/request.rb +77 -14
- data/lib/httpx/resolver/https.rb +17 -20
- data/lib/httpx/resolver/multi.rb +34 -16
- data/lib/httpx/resolver/native.rb +140 -61
- data/lib/httpx/resolver/resolver.rb +64 -19
- data/lib/httpx/resolver/system.rb +32 -16
- data/lib/httpx/resolver.rb +21 -14
- data/lib/httpx/response/body.rb +12 -1
- data/lib/httpx/response.rb +16 -9
- data/lib/httpx/selector.rb +170 -91
- data/lib/httpx/session.rb +282 -139
- data/lib/httpx/timers.rb +17 -2
- data/lib/httpx/transcoder/body.rb +15 -29
- data/lib/httpx/transcoder/form.rb +2 -0
- data/lib/httpx/transcoder/gzip.rb +0 -3
- data/lib/httpx/transcoder/json.rb +16 -2
- data/lib/httpx/transcoder/multipart/encoder.rb +11 -2
- data/lib/httpx/transcoder/multipart/part.rb +1 -1
- data/lib/httpx/transcoder/utils/deflater.rb +7 -4
- data/lib/httpx/transcoder.rb +0 -1
- data/lib/httpx/version.rb +1 -1
- data/lib/httpx.rb +20 -21
- data/sig/callbacks.rbs +2 -3
- data/sig/chainable.rbs +6 -2
- data/sig/connection/http1.rbs +2 -2
- data/sig/connection/http2.rbs +22 -18
- data/sig/connection.rbs +40 -9
- data/sig/errors.rbs +9 -3
- data/sig/httpx.rbs +3 -3
- data/sig/io/tcp.rbs +1 -1
- data/sig/io/unix.rbs +1 -1
- data/sig/loggable.rbs +4 -2
- data/sig/options.rbs +8 -13
- data/sig/plugins/aws_sigv4.rbs +8 -2
- data/sig/plugins/content_digest.rbs +51 -0
- data/sig/plugins/cookies/cookie.rbs +9 -0
- data/sig/plugins/follow_redirects.rbs +1 -1
- data/sig/plugins/grpc/call.rbs +4 -0
- data/sig/plugins/persistent.rbs +4 -1
- data/sig/plugins/proxy/http.rbs +3 -0
- data/sig/plugins/proxy/socks5.rbs +11 -3
- data/sig/plugins/proxy.rbs +18 -9
- data/sig/plugins/push_promise.rbs +6 -3
- data/sig/plugins/rate_limiter.rbs +2 -0
- data/sig/plugins/retries.rbs +1 -1
- data/sig/plugins/ssrf_filter.rbs +26 -0
- data/sig/plugins/stream.rbs +3 -0
- data/sig/plugins/webdav.rbs +23 -0
- data/sig/plugins/xml.rbs +37 -0
- data/sig/pool.rbs +27 -33
- data/sig/request/body.rbs +4 -10
- data/sig/request.rbs +14 -1
- data/sig/resolver/multi.rbs +26 -1
- data/sig/resolver/native.rbs +6 -3
- data/sig/resolver/resolver.rbs +22 -3
- data/sig/resolver.rbs +5 -1
- data/sig/response/body.rbs +2 -2
- data/sig/response/buffer.rbs +2 -2
- data/sig/response.rbs +9 -4
- data/sig/selector.rbs +31 -4
- data/sig/session.rbs +54 -20
- data/sig/timers.rbs +15 -4
- data/sig/transcoder/body.rbs +2 -4
- data/sig/transcoder/chunker.rbs +1 -1
- data/sig/transcoder/deflate.rbs +1 -0
- data/sig/transcoder/form.rbs +8 -0
- data/sig/transcoder/gzip.rbs +4 -1
- data/sig/transcoder/json.rbs +1 -1
- data/sig/transcoder/multipart.rbs +6 -4
- data/sig/transcoder/utils/body_reader.rbs +3 -3
- data/sig/transcoder/utils/deflater.rbs +2 -3
- metadata +32 -14
- data/lib/httpx/session2.rb +0 -23
- data/lib/httpx/transcoder/utils/inflater.rb +0 -19
- data/lib/httpx/transcoder/xml.rb +0 -52
- data/sig/transcoder/utils/inflater.rbs +0 -12
- data/sig/transcoder/xml.rbs +0 -22
data/lib/httpx/resolver.rb
CHANGED
@@ -53,8 +53,8 @@ module HTTPX
|
|
53
53
|
|
54
54
|
def cached_lookup(hostname)
|
55
55
|
now = Utils.now
|
56
|
-
|
57
|
-
lookup(hostname, now)
|
56
|
+
lookup_synchronize do |lookups|
|
57
|
+
lookup(hostname, lookups, now)
|
58
58
|
end
|
59
59
|
end
|
60
60
|
|
@@ -63,37 +63,37 @@ module HTTPX
|
|
63
63
|
entries.each do |entry|
|
64
64
|
entry["TTL"] += now
|
65
65
|
end
|
66
|
-
|
66
|
+
lookup_synchronize do |lookups|
|
67
67
|
case family
|
68
68
|
when Socket::AF_INET6
|
69
|
-
|
69
|
+
lookups[hostname].concat(entries)
|
70
70
|
when Socket::AF_INET
|
71
|
-
|
71
|
+
lookups[hostname].unshift(*entries)
|
72
72
|
end
|
73
73
|
entries.each do |entry|
|
74
74
|
next unless entry["name"] != hostname
|
75
75
|
|
76
76
|
case family
|
77
77
|
when Socket::AF_INET6
|
78
|
-
|
78
|
+
lookups[entry["name"]] << entry
|
79
79
|
when Socket::AF_INET
|
80
|
-
|
80
|
+
lookups[entry["name"]].unshift(entry)
|
81
81
|
end
|
82
82
|
end
|
83
83
|
end
|
84
84
|
end
|
85
85
|
|
86
86
|
# do not use directly!
|
87
|
-
def lookup(hostname, ttl)
|
88
|
-
return unless
|
87
|
+
def lookup(hostname, lookups, ttl)
|
88
|
+
return unless lookups.key?(hostname)
|
89
89
|
|
90
|
-
entries =
|
90
|
+
entries = lookups[hostname] = lookups[hostname].select do |address|
|
91
91
|
address["TTL"] > ttl
|
92
92
|
end
|
93
93
|
|
94
94
|
ips = entries.flat_map do |address|
|
95
95
|
if address.key?("alias")
|
96
|
-
lookup(address["alias"], ttl)
|
96
|
+
lookup(address["alias"], lookups, ttl)
|
97
97
|
else
|
98
98
|
IPAddr.new(address["data"])
|
99
99
|
end
|
@@ -103,12 +103,11 @@ module HTTPX
|
|
103
103
|
end
|
104
104
|
|
105
105
|
def generate_id
|
106
|
-
|
106
|
+
id_synchronize { @identifier = (@identifier + 1) & 0xFFFF }
|
107
107
|
end
|
108
108
|
|
109
109
|
def encode_dns_query(hostname, type: Resolv::DNS::Resource::IN::A, message_id: generate_id)
|
110
|
-
Resolv::DNS::Message.new.tap do |query|
|
111
|
-
query.id = message_id
|
110
|
+
Resolv::DNS::Message.new(message_id).tap do |query|
|
112
111
|
query.rd = 1
|
113
112
|
query.add_question(hostname, type)
|
114
113
|
end.encode
|
@@ -150,5 +149,13 @@ module HTTPX
|
|
150
149
|
|
151
150
|
[:ok, addresses]
|
152
151
|
end
|
152
|
+
|
153
|
+
def lookup_synchronize
|
154
|
+
@lookup_mutex.synchronize { yield(@lookups) }
|
155
|
+
end
|
156
|
+
|
157
|
+
def id_synchronize(&block)
|
158
|
+
@identifier_mutex.synchronize(&block)
|
159
|
+
end
|
153
160
|
end
|
154
161
|
end
|
data/lib/httpx/response/body.rb
CHANGED
@@ -17,12 +17,23 @@ module HTTPX
|
|
17
17
|
@headers = response.headers
|
18
18
|
@options = options
|
19
19
|
@window_size = options.window_size
|
20
|
-
@encoding = response.content_type.charset || Encoding::BINARY
|
21
20
|
@encodings = []
|
22
21
|
@length = 0
|
23
22
|
@buffer = nil
|
24
23
|
@reader = nil
|
25
24
|
@state = :idle
|
25
|
+
|
26
|
+
# initialize response encoding
|
27
|
+
@encoding = if (enc = response.content_type.charset)
|
28
|
+
begin
|
29
|
+
Encoding.find(enc)
|
30
|
+
rescue ArgumentError
|
31
|
+
Encoding::BINARY
|
32
|
+
end
|
33
|
+
else
|
34
|
+
Encoding::BINARY
|
35
|
+
end
|
36
|
+
|
26
37
|
initialize_inflaters
|
27
38
|
end
|
28
39
|
|
data/lib/httpx/response.rb
CHANGED
@@ -52,9 +52,6 @@ module HTTPX
|
|
52
52
|
# copies the response body to a different location.
|
53
53
|
def_delegator :@body, :copy_to
|
54
54
|
|
55
|
-
# closes the body.
|
56
|
-
def_delegator :@body, :close
|
57
|
-
|
58
55
|
# the corresponding request uri.
|
59
56
|
def_delegator :@request, :uri
|
60
57
|
|
@@ -74,6 +71,12 @@ module HTTPX
|
|
74
71
|
@content_type = nil
|
75
72
|
end
|
76
73
|
|
74
|
+
# closes the respective +@request+ and +@body+.
|
75
|
+
def close
|
76
|
+
@request.close
|
77
|
+
@body.close
|
78
|
+
end
|
79
|
+
|
77
80
|
# merges headers defined in +h+ into the response headers.
|
78
81
|
def merge_headers(h)
|
79
82
|
@headers = @headers.merge(h)
|
@@ -166,10 +169,12 @@ module HTTPX
|
|
166
169
|
decode(Transcoder::Form)
|
167
170
|
end
|
168
171
|
|
169
|
-
# decodes the response payload into a Nokogiri::XML::Node object **if** the payload is valid
|
170
|
-
# "application/xml" (requires the "nokogiri" gem).
|
171
172
|
def xml
|
172
|
-
|
173
|
+
# TODO: remove at next major version.
|
174
|
+
warn "DEPRECATION WARNING: calling `.#{__method__}` on plain HTTPX responses is deprecated. " \
|
175
|
+
"Use HTTPX.plugin(:xml) sessions and call `.#{__method__}` in its responses instead."
|
176
|
+
require "httpx/plugins/xml"
|
177
|
+
decode(Plugins::XML::Transcoder)
|
173
178
|
end
|
174
179
|
|
175
180
|
private
|
@@ -247,11 +252,11 @@ module HTTPX
|
|
247
252
|
# the IP address of the peer server.
|
248
253
|
def_delegator :@request, :peer_address
|
249
254
|
|
250
|
-
def initialize(request, error
|
255
|
+
def initialize(request, error)
|
251
256
|
@request = request
|
252
257
|
@response = request.response if request.response.is_a?(Response)
|
253
258
|
@error = error
|
254
|
-
@options =
|
259
|
+
@options = request.options
|
255
260
|
log_exception(@error)
|
256
261
|
end
|
257
262
|
|
@@ -262,7 +267,7 @@ module HTTPX
|
|
262
267
|
|
263
268
|
# closes the error resources.
|
264
269
|
def close
|
265
|
-
@response.close if @response
|
270
|
+
@response.close if @response
|
266
271
|
end
|
267
272
|
|
268
273
|
# always true for error responses.
|
@@ -277,6 +282,8 @@ module HTTPX
|
|
277
282
|
|
278
283
|
# buffers lost chunks to error response
|
279
284
|
def <<(data)
|
285
|
+
return unless @response
|
286
|
+
|
280
287
|
@response << data
|
281
288
|
end
|
282
289
|
end
|
data/lib/httpx/selector.rb
CHANGED
@@ -2,71 +2,142 @@
|
|
2
2
|
|
3
3
|
require "io/wait"
|
4
4
|
|
5
|
-
|
6
|
-
|
7
|
-
|
5
|
+
module HTTPX
|
6
|
+
class Selector
|
7
|
+
extend Forwardable
|
8
8
|
|
9
|
-
|
10
|
-
|
9
|
+
READABLE = %i[rw r].freeze
|
10
|
+
WRITABLE = %i[rw w].freeze
|
11
11
|
|
12
|
-
|
13
|
-
|
14
|
-
end
|
12
|
+
private_constant :READABLE
|
13
|
+
private_constant :WRITABLE
|
15
14
|
|
16
|
-
|
17
|
-
def deregister(io)
|
18
|
-
@selectables.delete(io)
|
19
|
-
end
|
15
|
+
def_delegator :@timers, :after
|
20
16
|
|
21
|
-
|
22
|
-
def register(io)
|
23
|
-
return if @selectables.include?(io)
|
17
|
+
def_delegator :@selectables, :empty?
|
24
18
|
|
25
|
-
|
26
|
-
|
19
|
+
def initialize
|
20
|
+
@timers = Timers.new
|
21
|
+
@selectables = []
|
22
|
+
@is_timer_interval = false
|
23
|
+
end
|
27
24
|
|
28
|
-
|
25
|
+
def each(&blk)
|
26
|
+
@selectables.each(&blk)
|
27
|
+
end
|
29
28
|
|
30
|
-
|
31
|
-
|
29
|
+
def next_tick
|
30
|
+
catch(:jump_tick) do
|
31
|
+
timeout = next_timeout
|
32
|
+
if timeout && timeout.negative?
|
33
|
+
@timers.fire
|
34
|
+
throw(:jump_tick)
|
35
|
+
end
|
32
36
|
|
33
|
-
# first, we group IOs based on interest type. On call to #interests however,
|
34
|
-
# things might already happen, and new IOs might be registered, so we might
|
35
|
-
# have to start all over again. We do this until we group all selectables
|
36
|
-
begin
|
37
|
-
loop do
|
38
37
|
begin
|
39
|
-
|
40
|
-
|
38
|
+
select(timeout, &:call)
|
39
|
+
@timers.fire
|
40
|
+
rescue TimeoutError => e
|
41
|
+
@timers.fire(e)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
rescue StandardError => e
|
45
|
+
emit_error(e)
|
46
|
+
rescue Exception # rubocop:disable Lint/RescueException
|
47
|
+
each_connection do |conn|
|
48
|
+
conn.force_reset
|
49
|
+
conn.disconnect
|
50
|
+
end
|
41
51
|
|
42
|
-
|
43
|
-
|
52
|
+
raise
|
53
|
+
end
|
44
54
|
|
45
|
-
|
46
|
-
|
55
|
+
def terminate
|
56
|
+
# array may change during iteration
|
57
|
+
selectables = @selectables.reject(&:inflight?)
|
47
58
|
|
48
|
-
|
49
|
-
(w ||= []) << io if WRITABLE.include?(interests)
|
59
|
+
selectables.each(&:terminate)
|
50
60
|
|
51
|
-
|
52
|
-
|
61
|
+
until selectables.empty?
|
62
|
+
next_tick
|
53
63
|
|
54
|
-
|
55
|
-
|
64
|
+
selectables &= @selectables
|
65
|
+
end
|
66
|
+
end
|
56
67
|
|
57
|
-
|
58
|
-
|
59
|
-
|
68
|
+
def find_resolver(options)
|
69
|
+
res = @selectables.find do |c|
|
70
|
+
c.is_a?(Resolver::Resolver) && options == c.options
|
71
|
+
end
|
72
|
+
|
73
|
+
res.multi if res
|
74
|
+
end
|
60
75
|
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
76
|
+
def each_connection(&block)
|
77
|
+
return enum_for(__method__) unless block
|
78
|
+
|
79
|
+
@selectables.each do |c|
|
80
|
+
if c.is_a?(Resolver::Resolver)
|
81
|
+
c.each_connection(&block)
|
82
|
+
else
|
83
|
+
yield c
|
68
84
|
end
|
69
85
|
end
|
86
|
+
end
|
87
|
+
|
88
|
+
def find_connection(request_uri, options)
|
89
|
+
each_connection.find do |connection|
|
90
|
+
connection.match?(request_uri, options)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
def find_mergeable_connection(connection)
|
95
|
+
each_connection.find do |ch|
|
96
|
+
ch != connection && ch.mergeable?(connection)
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
# deregisters +io+ from selectables.
|
101
|
+
def deregister(io)
|
102
|
+
@selectables.delete(io)
|
103
|
+
end
|
104
|
+
|
105
|
+
# register +io+.
|
106
|
+
def register(io)
|
107
|
+
return if @selectables.include?(io)
|
108
|
+
|
109
|
+
@selectables << io
|
110
|
+
end
|
111
|
+
|
112
|
+
private
|
113
|
+
|
114
|
+
def select(interval, &block)
|
115
|
+
# do not cause an infinite loop here.
|
116
|
+
#
|
117
|
+
# this may happen if timeout calculation actually triggered an error which causes
|
118
|
+
# the connections to be reaped (such as the total timeout error) before #select
|
119
|
+
# gets called.
|
120
|
+
return if interval.nil? && @selectables.empty?
|
121
|
+
|
122
|
+
return select_one(interval, &block) if @selectables.size == 1
|
123
|
+
|
124
|
+
select_many(interval, &block)
|
125
|
+
end
|
126
|
+
|
127
|
+
def select_many(interval, &block)
|
128
|
+
r, w = nil
|
129
|
+
|
130
|
+
# first, we group IOs based on interest type. On call to #interests however,
|
131
|
+
# things might already happen, and new IOs might be registered, so we might
|
132
|
+
# have to start all over again. We do this until we group all selectables
|
133
|
+
@selectables.delete_if do |io|
|
134
|
+
interests = io.interests
|
135
|
+
|
136
|
+
(r ||= []) << io if READABLE.include?(interests)
|
137
|
+
(w ||= []) << io if WRITABLE.include?(interests)
|
138
|
+
|
139
|
+
io.state == :closed
|
140
|
+
end
|
70
141
|
|
71
142
|
# TODO: what to do if there are no selectables?
|
72
143
|
|
@@ -76,63 +147,71 @@ class HTTPX::Selector
|
|
76
147
|
[*r, *w].each { |io| io.handle_socket_timeout(interval) }
|
77
148
|
return
|
78
149
|
end
|
79
|
-
rescue IOError, SystemCallError
|
80
|
-
@selectables.reject!(&:closed?)
|
81
|
-
retry
|
82
|
-
end
|
83
150
|
|
84
|
-
|
85
|
-
|
86
|
-
|
151
|
+
if writers
|
152
|
+
readers.each do |io|
|
153
|
+
yield io
|
87
154
|
|
88
|
-
|
89
|
-
|
90
|
-
|
155
|
+
# so that we don't yield 2 times
|
156
|
+
writers.delete(io)
|
157
|
+
end if readers
|
91
158
|
|
92
|
-
|
93
|
-
|
94
|
-
|
159
|
+
writers.each(&block)
|
160
|
+
else
|
161
|
+
readers.each(&block) if readers
|
162
|
+
end
|
95
163
|
end
|
96
|
-
end
|
97
164
|
|
98
|
-
|
99
|
-
|
165
|
+
def select_one(interval)
|
166
|
+
io = @selectables.first
|
100
167
|
|
101
|
-
|
168
|
+
return unless io
|
102
169
|
|
103
|
-
|
170
|
+
interests = io.interests
|
104
171
|
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
172
|
+
result = case interests
|
173
|
+
when :r then io.to_io.wait_readable(interval)
|
174
|
+
when :w then io.to_io.wait_writable(interval)
|
175
|
+
when :rw then io.to_io.wait(interval, :read_write)
|
176
|
+
when nil then return
|
177
|
+
end
|
111
178
|
|
112
|
-
|
113
|
-
|
114
|
-
|
179
|
+
unless result || interval.nil?
|
180
|
+
io.handle_socket_timeout(interval) unless @is_timer_interval
|
181
|
+
return
|
182
|
+
end
|
183
|
+
# raise TimeoutError.new(interval, "timed out while waiting on select")
|
184
|
+
|
185
|
+
yield io
|
186
|
+
# rescue IOError, SystemCallError
|
187
|
+
# @selectables.reject!(&:closed?)
|
188
|
+
# raise unless @selectables.empty?
|
115
189
|
end
|
116
|
-
# raise HTTPX::TimeoutError.new(interval, "timed out while waiting on select")
|
117
190
|
|
118
|
-
|
119
|
-
|
120
|
-
@selectables.reject!(&:closed?)
|
121
|
-
raise unless @selectables.empty?
|
122
|
-
end
|
191
|
+
def next_timeout
|
192
|
+
@is_timer_interval = false
|
123
193
|
|
124
|
-
|
125
|
-
# do not cause an infinite loop here.
|
126
|
-
#
|
127
|
-
# this may happen if timeout calculation actually triggered an error which causes
|
128
|
-
# the connections to be reaped (such as the total timeout error) before #select
|
129
|
-
# gets called.
|
130
|
-
return if interval.nil? && @selectables.empty?
|
194
|
+
timer_interval = @timers.wait_interval
|
131
195
|
|
132
|
-
|
196
|
+
connection_interval = @selectables.filter_map(&:timeout).min
|
133
197
|
|
134
|
-
|
135
|
-
|
198
|
+
return connection_interval unless timer_interval
|
199
|
+
|
200
|
+
if connection_interval.nil? || timer_interval <= connection_interval
|
201
|
+
@is_timer_interval = true
|
202
|
+
|
203
|
+
return timer_interval
|
204
|
+
end
|
205
|
+
|
206
|
+
connection_interval
|
207
|
+
end
|
208
|
+
|
209
|
+
def emit_error(e)
|
210
|
+
@selectables.each do |c|
|
211
|
+
next if c.is_a?(Resolver::Resolver)
|
136
212
|
|
137
|
-
|
213
|
+
c.emit(:error, e)
|
214
|
+
end
|
215
|
+
end
|
216
|
+
end
|
138
217
|
end
|