mirror of
https://github.com/discourse/discourse.git
synced 2026-08-05 21:57:36 +08:00
The Happy Eyeballs patch prepends an `open` singleton method onto TCPSocket, and TCPServer inherits it because TCPServer < TCPSocket. With a fixed host/port signature, `TCPServer.open(port)` raised ArgumentError before `super` could run. That broke TemporaryDb#port_available? and, in turn, the migrations tooling's `disco check` plugin-manifest refresh. The patched `open` now takes *args and forwards the caller's arguments untouched to `super` for non-token hosts, so subclasses with looser signatures keep working.
50 lines
1.7 KiB
Ruby
Vendored
50 lines
1.7 KiB
Ruby
Vendored
# frozen_string_literal: true
|
|
|
|
# Patch getaddrinfo to recognize `FinalDestination::Connector` tokens
|
|
# and return their IPs instead of doing a true lookup.
|
|
module FinalDestinationAddrinfoPatch
|
|
def getaddrinfo(nodename, service, family = nil, *args, **kwargs)
|
|
return super unless FinalDestination::Connector.token?(nodename)
|
|
|
|
ips =
|
|
FinalDestination::Connector.addresses_for_family(
|
|
FinalDestination::Connector.addresses(nodename),
|
|
family,
|
|
)
|
|
raise SocketError, "getaddrinfo: Address family for hostname not supported" if ips.empty?
|
|
|
|
ips.map { |ip| Addrinfo.tcp(ip, service.to_i) }
|
|
end
|
|
end
|
|
|
|
# TCPSocket.open uses a C-based implementation by default, which would bypass our
|
|
# getaddrinfo patch. Instead, open the socket with `Socket.tcp`, then set up a `TCPSocket`
|
|
# instance with the result.
|
|
module FinalDestinationTCPSocketPatch
|
|
# Takes *args because TCPServer inherits this singleton method and
|
|
# `TCPServer.open(port)` has fewer arguments — a fixed host/port signature
|
|
# fails the arity check before `super` can run. A bare `super` forwards the
|
|
# original arguments untouched.
|
|
def open(*args, **kwargs)
|
|
host = args[0]
|
|
return super unless FinalDestination::Connector.token?(host)
|
|
|
|
_, port, local_host, local_port = args
|
|
|
|
socket =
|
|
Socket.tcp(
|
|
host,
|
|
port,
|
|
local_host,
|
|
local_port,
|
|
connect_timeout: kwargs[:open_timeout],
|
|
fast_fallback: true,
|
|
)
|
|
socket.autoclose = false # Let the TCPSocket handle closing
|
|
|
|
TCPSocket.for_fd(socket.fileno)
|
|
end
|
|
end
|
|
|
|
Addrinfo.singleton_class.prepend(FinalDestinationAddrinfoPatch)
|
|
TCPSocket.singleton_class.prepend(FinalDestinationTCPSocketPatch)
|