discourse/lib/final_destination/resolver.rb

57 lines
1.1 KiB
Ruby

# frozen_string_literal: true
class FinalDestination::Resolver
@mutex = Mutex.new
def self.lookup(addr, timeout: nil)
timeout ||= 2
@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.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