remove dependency on error having a connection in the faraday adapter

connection reference should not remain in the response which goes to the user, as that may leak the reference which will block garbage collection of objects in the selector
This commit is contained in:
HoneyryderChuck 2025-08-12 15:23:01 +01:00
parent fbd1981a2d
commit c78c88b0f8
6 changed files with 41 additions and 25 deletions

View File

@ -68,16 +68,7 @@ module Datadog::Tracing
end
request.on(:response) do |response|
unless span
next unless response.is_a?(::HTTPX::ErrorResponse) && response.error.respond_to?(:connection)
# handles the case when the +error+ happened during name resolution, which means
# that the tracing start point hasn't been triggered yet; in such cases, the approximate
# initial resolving time is collected from the connection, and used as span start time,
# and the tracing object in inserted before the on response callback is called.
span = initialize_span(request, response.error.connection.init_time)
end
span = initialize_span(request, request.init_time) if !span && request.init_time
finish(response, span)
end
@ -189,14 +180,29 @@ module Datadog::Tracing
end
module RequestMethods
attr_reader :init_time
# intercepts request initialization to inject the tracing logic.
def initialize(*)
super
@init_time = nil
return unless Datadog::Tracing.enabled?
RequestTracer.call(self)
end
def response=(response)
if response.is_a?(::HTTPX::ErrorResponse) && response.error.respond_to?(:connection)
# handles the case when the +error+ happened during name resolution, which means
# that the tracing start point hasn't been triggered yet; in such cases, the approximate
# initial resolving time is collected from the connection, and used as span start time,
# and the tracing object in inserted before the on response callback is called.
@init_time = response.error.connection.init_time
end
super
end
end
module ConnectionMethods

View File

@ -132,9 +132,11 @@ module Faraday
def response=(response)
super
return if response.is_a?(::HTTPX::ErrorResponse)
return unless @response
response.body.on_data = @response_on_data
return if @response.is_a?(::HTTPX::ErrorResponse)
@response.body.on_data = @response_on_data
end
end

View File

@ -77,7 +77,9 @@ module HTTPX
# Error raised when there was an error while resolving a domain to an IP
# using a HTTPX::Resolver::Native resolver.
class NativeResolveError < ResolveError
attr_reader :connection, :host
attr_reader :host
attr_accessor :connection
# initializes the exception with the +connection+ it refers to, the +host+ domain
# which failed to resolve, and the error +message+.

View File

@ -220,10 +220,10 @@ module HTTPX
when NativeResolveError
proxy_uri = URI(options.proxy.uri)
peer = error.connection.peer
unresolved_host = error.host
# failed resolving proxy domain
peer.host == proxy_uri.host && peer.port == proxy_uri.port
unresolved_host == proxy_uri.host
when ResolveError
proxy_uri = URI(options.proxy.uri)

View File

@ -177,17 +177,23 @@ module HTTPX
def response=(response)
return unless response
if response.is_a?(Response) && response.status < 200
# deal with informational responses
case response
when Response
if response.status < 200
# deal with informational responses
if response.status == 100 && @headers.key?("expect")
@informational_status = response.status
return
end
# 103 Early Hints advertises resources in document to browsers.
# not very relevant for an HTTP client, discard.
return if response.status >= 103
if response.status == 100 && @headers.key?("expect")
@informational_status = response.status
return
end
# 103 Early Hints advertises resources in document to browsers.
# not very relevant for an HTTP client, discard.
return if response.status >= 103
when ErrorResponse
response.error.connection = nil if response.error.respond_to?(:connection=)
end
@response = response

View File

@ -59,7 +59,7 @@ module HTTPX
end
class NativeResolveError < ResolveError
attr_reader connection: Connection
attr_accessor connection: Connection?
attr_reader host: String
private