lib/httpx/connection.rb in httpx-0.22.2 vs lib/httpx/connection.rb in httpx-0.22.3
- old
+ new
@@ -43,14 +43,16 @@
def_delegator :@io, :closed?
def_delegator :@write_buffer, :empty?
- attr_reader :io, :origin, :origins, :state, :pending, :options
+ attr_reader :type, :io, :origin, :origins, :state, :pending, :options
attr_writer :timers
+ attr_accessor :family
+
def initialize(type, uri, options)
@type = type
@origins = [uri.origin]
@origin = Utils.to_uri(uri.origin)
@options = Options.new(options)
@@ -74,17 +76,10 @@
@total_timeout = @options.timeout[:total_timeout]
self.addresses = @options.addresses if @options.addresses
end
- def clone_new_connection
- new_conn = self.class.new(@type, @origin, @options)
- once(:open, &new_conn.method(:reset))
- new_conn.once(:open, &method(:close))
- new_conn
- end
-
# this is a semi-private method, to be used by the resolver
# to initiate the io object.
def addresses=(addrs)
if @io
@io.add_addresses(addrs)
@@ -119,11 +114,14 @@
return false if exhausted?
return false unless connection.addresses
- !(@io.addresses & connection.addresses).empty? && @options == connection.options
+ (
+ (open? && @origin == connection.origin) ||
+ !(@io.addresses & connection.addresses).empty?
+ ) && @options == connection.options
end
# coalescable connections need to be mergeable!
# but internally, #mergeable? is called before #coalescable?
def coalescable?(connection)
@@ -224,10 +222,18 @@
transition(:active) if @state == :inactive
@parser.close if @parser
end
+ # bypasses the state machine to force closing of connections still connecting.
+ # **only** used for Happy Eyeballs v2.
+ def force_reset
+ @state = :closing
+ transition(:closed)
+ emit(:close)
+ end
+
def reset
transition(:closing)
transition(:closed)
emit(:close)
end
@@ -314,11 +320,11 @@
# this condition takes into account:
#
# * the number of inflight requests
# * the number of pending requests
# * whether the write buffer has bytes (i.e. for close handshake)
- if @pending.size.zero? && @inflight.zero? && @write_buffer.empty?
+ if @pending.empty? && @inflight.zero? && @write_buffer.empty?
log(level: 3) { "NO MORE REQUESTS..." }
return
end
@timeout = @current_timeout
@@ -358,11 +364,11 @@
# exit the read loop if connection is preparing to be closed
break if @state == :closing || @state == :closed
# exit #consume altogether if all outstanding requests have been dealt with
- return if @pending.size.zero? && @inflight.zero?
+ return if @pending.empty? && @inflight.zero?
end unless ((ints = interests).nil? || ints == :w || @state == :closing) && !epiped
#
# tight write loop.
#
@@ -524,15 +530,17 @@
Errno::ECONNRESET,
Errno::EADDRNOTAVAIL,
Errno::EHOSTUNREACH,
Errno::EINVAL,
Errno::ENETUNREACH,
- Errno::EPIPE => e
+ Errno::EPIPE,
+ Errno::ENOENT,
+ SocketError => e
# connect errors, exit gracefully
error = ConnectionError.new(e.message)
error.set_backtrace(e.backtrace)
- handle_error(error)
+ connecting? && callbacks(:connect_error).any? ? emit(:connect_error, error) : handle_error(error)
@state = :closed
emit(:close)
rescue TLSError => e
# connect errors, exit gracefully
handle_error(e)
@@ -547,9 +555,11 @@
when :open
return if @state == :closed
@io.connect
+ emit(:tcp_open, self) if @io.state == :connected
+
return unless @io.connected?
@connected_at = Utils.now
send_pending