native resolver: fix stalled resolution on multiple requests to multiple origins

continue resolving when an error happens by immediately writing to the buffer afterwards
This commit is contained in:
HoneyryderChuck 2025-02-10 18:16:23 +00:00
parent 86cb30926f
commit f76be1983b
2 changed files with 19 additions and 10 deletions

View File

@ -175,7 +175,8 @@ module HTTPX
ex = ResolveTimeoutError.new(loop_time, "Timed out while resolving #{connection.peer.host}") ex = ResolveTimeoutError.new(loop_time, "Timed out while resolving #{connection.peer.host}")
ex.set_backtrace(ex ? ex.backtrace : caller) ex.set_backtrace(ex ? ex.backtrace : caller)
emit_resolve_error(connection, host, ex) emit_resolve_error(connection, host, ex)
emit(:close, self)
close_or_resolve
end end
end end
@ -257,15 +258,15 @@ module HTTPX
hostname, connection = @queries.first hostname, connection = @queries.first
reset_hostname(hostname, reset_candidates: false) reset_hostname(hostname, reset_candidates: false)
unless @queries.value?(connection) if @queries.value?(connection)
resolve
else
@connections.delete(connection) @connections.delete(connection)
ex = NativeResolveError.new(connection, connection.peer.host, "name or service not known") ex = NativeResolveError.new(connection, connection.peer.host, "name or service not known")
ex.set_backtrace(ex ? ex.backtrace : caller) ex.set_backtrace(ex ? ex.backtrace : caller)
emit_resolve_error(connection, connection.peer.host, ex) emit_resolve_error(connection, connection.peer.host, ex)
emit(:close, self) close_or_resolve
end end
resolve
when :message_truncated when :message_truncated
# TODO: what to do if it's already tcp?? # TODO: what to do if it's already tcp??
return if @socket_type == :tcp return if @socket_type == :tcp
@ -346,9 +347,7 @@ module HTTPX
catch(:coalesced) { emit_addresses(connection, @family, addresses.map { |addr| addr["data"] }) } catch(:coalesced) { emit_addresses(connection, @family, addresses.map { |addr| addr["data"] }) }
end end
end end
return emit(:close, self) if @connections.empty? close_or_resolve
resolve
end end
def resolve(connection = @connections.first, hostname = nil) def resolve(connection = @connections.first, hostname = nil)
@ -378,7 +377,7 @@ module HTTPX
reset_hostname(hostname, connection: connection) reset_hostname(hostname, connection: connection)
@connections.delete(connection) @connections.delete(connection)
emit_resolve_error(connection, hostname, e) emit_resolve_error(connection, hostname, e)
emit(:close, self) if @connections.empty? close_or_resolve
end end
end end
@ -474,7 +473,7 @@ module HTTPX
emit_resolve_error(connection, host, error) emit_resolve_error(connection, host, error)
end end
end end
emit(:close, self) if @connections.empty? close_or_resolve
end end
def reset_hostname(hostname, connection: @queries.delete(hostname), reset_candidates: true) def reset_hostname(hostname, connection: @queries.delete(hostname), reset_candidates: true)
@ -489,5 +488,13 @@ module HTTPX
# reset timeouts # reset timeouts
@timeouts.delete_if { |h, _| candidates.include?(h) } @timeouts.delete_if { |h, _| candidates.include?(h) }
end end
def close_or_resolve
if @connections.empty?
emit(:close, self)
else
resolve
end
end
end end
end end

View File

@ -64,6 +64,8 @@ module HTTPX
def handle_error: (NativeResolveError | StandardError) -> void def handle_error: (NativeResolveError | StandardError) -> void
def reset_hostname: (String hostname, ?connection: Connection, ?reset_candidates: bool) -> void def reset_hostname: (String hostname, ?connection: Connection, ?reset_candidates: bool) -> void
def close_or_resolve: () -> void
end end
end end
end end