Skip to content

Happy eyeballs (fast fallback) in an Async environment? #409

@travisbell

Description

@travisbell

Hey Samuel,

I came across a bit of unique scenario with regards to a dual stack DNS address that I am trying to figure out. To be fair, this doesn't affect our production environment but is something I noticed in my local development environment since we connect to a VPN with only IPv4 addresses.

irb(main):009> Resolv.getaddresses("some-random-aws-service.aos.us-east-1.on.aws")
=> ["2600:1f28:372:c403:ccda:45e8:2797:6b54", "172.24.186.66"]
irb(main):010> Addrinfo.ip("some-random-aws-service.aos.us-east-1.on.aws")
=> #<Addrinfo: 2600:1f28:372:c403:ccda:45e8:2797:6b54 (some-random-aws-service.aos.us-east-1.on.aws)>

When I try and use this address with Async::HTTP, I just get a timeout because it's trying to connect to the (I think first(?) address which is IPv6:

irb(main):005> Async::HTTP::Internet.get("https://some-random-aws-service.aos.us-east-1.on.aws")
/Users/travisbell/.rbenv/versions/3.4.5/lib/ruby/gems/3.4.0/gems/io-endpoint-0.15.2/lib/io/endpoint/wrapper.rb:58:in 'Socket#connect': Operation timed out - connect(2) for [2600:1f28:372:c403:ccda:45e8:2797:6b54]:443 (Errno::ETIMEDOUT)
	from /Users/travisbell/.rbenv/versions/3.4.5/lib/ruby/gems/3.4.0/gems/io-endpoint-0.15.2/lib/io/endpoint/wrapper.rb:58:in 'IO::Endpoint::Wrapper#socket_connect'
	from /Users/travisbell/.rbenv/versions/3.4.5/lib/ruby/gems/3.4.0/gems/io-endpoint-0.15.2/lib/io/endpoint/wrapper.rb:99:in 'IO::Endpoint::Wrapper#connect'
	from /Users/travisbell/.rbenv/versions/3.4.5/lib/ruby/gems/3.4.0/gems/io-endpoint-0.15.2/lib/io/endpoint/host_endpoint.rb:46:in 'block in IO::Endpoint::HostEndpoint#connect'
	from /Users/travisbell/.rbenv/versions/3.4.5/lib/ruby/3.4.0/socket.rb:231:in 'Array#each'
	from /Users/travisbell/.rbenv/versions/3.4.5/lib/ruby/3.4.0/socket.rb:231:in 'Addrinfo.foreach'
	from /Users/travisbell/.rbenv/versions/3.4.5/lib/ruby/gems/3.4.0/gems/io-endpoint-0.15.2/lib/io/endpoint/host_endpoint.rb:44:in 'IO::Endpoint::HostEndpoint#connect'
	from /Users/travisbell/.rbenv/versions/3.4.5/lib/ruby/gems/3.4.0/gems/io-endpoint-0.15.2/lib/io/endpoint/ssl_endpoint.rb:159:in 'IO::Endpoint::SSLEndpoint#connect'
	from /Users/travisbell/.rbenv/versions/3.4.5/lib/ruby/gems/3.4.0/gems/async-http-0.89.0/lib/async/http/endpoint.rb:220:in 'Async::HTTP::Endpoint#connect'
	from /Users/travisbell/.rbenv/versions/3.4.5/lib/ruby/gems/3.4.0/gems/async-http-0.89.0/lib/async/http/client.rb:169:in 'block in Async::HTTP::Client#make_pool'
	from /Users/travisbell/.rbenv/versions/3.4.5/lib/ruby/gems/3.4.0/gems/async-pool-0.11.0/lib/async/pool/controller.rb:324:in 'Async::Pool::Controller#create_resource'
	from /Users/travisbell/.rbenv/versions/3.4.5/lib/ruby/gems/3.4.0/gems/async-pool-0.11.0/lib/async/pool/controller.rb:394:in 'Async::Pool::Controller#acquire_or_create_resource'
	from /Users/travisbell/.rbenv/versions/3.4.5/lib/ruby/gems/3.4.0/gems/async-pool-0.11.0/lib/async/pool/controller.rb:343:in 'block in Async::Pool::Controller#available_resource'
	from /Users/travisbell/.rbenv/versions/3.4.5/lib/ruby/gems/3.4.0/gems/async-2.27.0/lib/async/semaphore.rb:87:in 'Async::Semaphore#acquire'
	from /Users/travisbell/.rbenv/versions/3.4.5/lib/ruby/gems/3.4.0/gems/async-pool-0.11.0/lib/async/pool/controller.rb:342:in 'Async::Pool::Controller#available_resource'
	from /Users/travisbell/.rbenv/versions/3.4.5/lib/ruby/gems/3.4.0/gems/async-pool-0.11.0/lib/async/pool/controller.rb:312:in 'Async::Pool::Controller#wait_for_resource'
	from /Users/travisbell/.rbenv/versions/3.4.5/lib/ruby/gems/3.4.0/gems/async-pool-0.11.0/lib/async/pool/controller.rb:155:in 'Async::Pool::Controller#acquire'

Yet, when I use Net::HTTP, everything succeeds:

irb(main):006> Net::HTTP.get(URI("https://some-random-aws-service.aos.us-east-1.on.aws"))
=> "successful response body..."

I know a lot of work was done in Ruby 3.4 to support happy eyeballs v2 (RFC8305)... is this something we need to also build out in the Async libraries?

Thanks as always!

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions