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