mirror of
https://github.com/HoneyryderChuck/httpx.git
synced 2025-08-10 00:01:27 -04:00
making the connection ping when keep alive timeout is exceeded; this way if the connection is still available, it's reused
This commit is contained in:
parent
754bb6b5ed
commit
bb310dc106
@ -88,8 +88,6 @@ module HTTPX
|
||||
|
||||
return false if exhausted?
|
||||
|
||||
return false if @keep_alive_timer && @keep_alive_timer.fires_in.negative?
|
||||
|
||||
(
|
||||
(
|
||||
@origins.include?(uri.origin) &&
|
||||
@ -107,8 +105,6 @@ module HTTPX
|
||||
|
||||
return false if exhausted?
|
||||
|
||||
return false if @keep_alive_timer && @keep_alive_timer.fires_in.negative?
|
||||
|
||||
!(@io.addresses & connection.addresses).empty? && @options == connection.options
|
||||
end
|
||||
|
||||
@ -229,8 +225,18 @@ module HTTPX
|
||||
def send(request)
|
||||
if @parser && !@write_buffer.full?
|
||||
request.headers["alt-used"] = @origin.authority if match_altsvcs?(request.uri)
|
||||
if @keep_alive_timer
|
||||
# when pushing a request into an existing connection, we have to check whether there
|
||||
# is the possibility that the connection might have extended the keep alive timeout.
|
||||
# for such cases, we want to ping for availability before deciding to shovel requests.
|
||||
if @keep_alive_timer.fires_in.negative?
|
||||
parser.ping
|
||||
return
|
||||
end
|
||||
|
||||
@keep_alive_timer.pause
|
||||
end
|
||||
@inflight += 1
|
||||
@keep_alive_timer.pause if @keep_alive_timer
|
||||
parser.send(request)
|
||||
else
|
||||
@pending << request
|
||||
@ -361,6 +367,8 @@ module HTTPX
|
||||
emit(:altsvc, alt_origin, origin, alt_params)
|
||||
end
|
||||
|
||||
parser.on(:pong, &method(:send_pending))
|
||||
|
||||
parser.on(:promise) do |request, stream|
|
||||
request.emit(:promise, parser, stream)
|
||||
end
|
||||
@ -469,8 +477,8 @@ module HTTPX
|
||||
else
|
||||
@keep_alive_timer = @timers.after(@keep_alive_timeout) do
|
||||
unless @inflight.zero?
|
||||
log { "(#{object_id})) keep alive timeout expired, closing..." }
|
||||
reset
|
||||
log { "(#{@origin}): keep alive timeout expired" }
|
||||
parser.ping
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -1,5 +1,6 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require "securerandom"
|
||||
require "io/wait"
|
||||
require "http/2/next"
|
||||
|
||||
@ -109,6 +110,11 @@ module HTTPX
|
||||
end
|
||||
end
|
||||
|
||||
def ping
|
||||
@ping_payload = SecureRandom.bytes(8)
|
||||
@connection.ping(@ping_payload)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def send_pending
|
||||
@ -143,6 +149,7 @@ module HTTPX
|
||||
@connection.on(:promise, &method(:on_promise))
|
||||
@connection.on(:altsvc) { |frame| on_altsvc(frame[:origin], frame) }
|
||||
@connection.on(:settings_ack, &method(:on_settings))
|
||||
@connection.on(:ack, &method(:on_pong))
|
||||
@connection.on(:goaway, &method(:on_close))
|
||||
#
|
||||
# Some servers initiate HTTP/2 negotiation right away, some don't.
|
||||
@ -306,6 +313,13 @@ module HTTPX
|
||||
emit(:origin, origin)
|
||||
end
|
||||
|
||||
def on_pong(_payload)
|
||||
# TODO: what to do when ping doesn't match
|
||||
emit(:pong)
|
||||
ensure
|
||||
@ping_payload = nil
|
||||
end
|
||||
|
||||
def respond_to_missing?(meth, *args)
|
||||
@connection.respond_to?(meth, *args) || super
|
||||
end
|
||||
|
@ -96,8 +96,8 @@ class SessionTest < Minitest::Test
|
||||
|
||||
verify_status(response1, 200)
|
||||
verify_status(response2, 200)
|
||||
connection_count = http.pool.connection_count
|
||||
assert connection_count == 2, "session should have closed the first connection (#{connection_count})"
|
||||
ping_count = http.pool.ping_count
|
||||
assert ping_count == 1, "session should have pinged after timeout (#{ping_count})"
|
||||
end
|
||||
end unless RUBY_VERSION < "2.3" || RUBY_ENGINE == "jruby"
|
||||
|
||||
|
@ -25,15 +25,18 @@ module SessionWithPool
|
||||
ConnectionPool = Class.new(HTTPX::Pool) do
|
||||
attr_reader :connections
|
||||
attr_reader :connection_count
|
||||
attr_reader :ping_count
|
||||
|
||||
def initialize(*)
|
||||
super
|
||||
@connection_count = 0
|
||||
@ping_count = 0
|
||||
end
|
||||
|
||||
def init_connection(connection, _)
|
||||
super
|
||||
connection.on(:open) { @connection_count += 1 }
|
||||
connection.on(:pong) { @ping_count += 1 }
|
||||
end
|
||||
end
|
||||
|
||||
@ -42,6 +45,13 @@ module SessionWithPool
|
||||
@pool ||= ConnectionPool.new
|
||||
end
|
||||
end
|
||||
|
||||
module ConnectionMethods
|
||||
def set_parser_callbacks(parser)
|
||||
super
|
||||
parser.on(:pong) { emit(:pong) }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# 9090 drops SYN packets for connect timeout tests, make sure there's a server binding there.
|
||||
|
Loading…
x
Reference in New Issue
Block a user