mirror of
https://github.com/discourse/discourse.git
synced 2024-11-30 09:14:36 +08:00
509fee0f5a
The current default timeout is hardcoded to 2 seconds which is proving too low for certain cases, and resulting in sporadic timeouts due to slow DNS queries.
67 lines
1.3 KiB
Ruby
67 lines
1.3 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
class FinalDestination::Resolver
|
|
@mutex = Mutex.new
|
|
def self.lookup(addr, timeout: nil)
|
|
timeout ||= default_dns_query_timeout
|
|
|
|
@mutex.synchronize do
|
|
@result = nil
|
|
|
|
@queue ||= Queue.new
|
|
ensure_lookup_thread
|
|
|
|
@lookup = addr
|
|
@parent = Thread.current
|
|
|
|
# Wakeup the worker thread
|
|
@queue << ""
|
|
|
|
# This sleep will be interrupted by the lookup thread
|
|
# if completed within timeout
|
|
sleep timeout
|
|
if !@result
|
|
@thread.kill
|
|
@thread.join
|
|
@thread = nil
|
|
if @error
|
|
@error.backtrace.push(*caller)
|
|
raise @error
|
|
else
|
|
raise Timeout::Error
|
|
end
|
|
end
|
|
@result
|
|
end
|
|
end
|
|
|
|
private
|
|
|
|
def self.default_dns_query_timeout
|
|
if gs = GlobalSetting.dns_query_timeout_secs.presence
|
|
Integer(gs)
|
|
else
|
|
2
|
|
end
|
|
end
|
|
|
|
def self.ensure_lookup_thread
|
|
return if @thread&.alive?
|
|
|
|
@thread =
|
|
Thread.new do
|
|
while true
|
|
@queue.deq
|
|
@error = nil
|
|
begin
|
|
@result = Addrinfo.getaddrinfo(@lookup, 80, nil, :STREAM).map(&:ip_address)
|
|
rescue => e
|
|
@error = e
|
|
end
|
|
@parent.wakeup
|
|
end
|
|
end
|
|
@thread.name = "final-destination_resolver_thread"
|
|
end
|
|
end
|