class HTTPX::Resolver::System

  1. lib/httpx/resolver/system.rb
Superclass: Resolver

Implementation of a synchronous name resolver which relies on the system resolver, which is lib’c getaddrinfo function (abstracted in ruby via Addrinfo.getaddrinfo).

Its main advantage is relying on the reference implementation for name resolution across most/all OSs which deploy ruby (it’s what TCPSocket also uses), its main disadvantage is the inability to set timeouts / check socket for readiness events, hence why it relies on using the Timeout module, which poses a lot of problems for the selector loop, specially when network is unstable.

Constants

DONE = 1  
ERROR = 2  
RESOLV_ERRORS = [Resolv::ResolvError, Resolv::DNS::Requester::RequestError, Resolv::DNS::EncodeError, Resolv::DNS::DecodeError].freeze  

Attributes

state [R]

Public Class methods

multi?()
[show source]
   # File lib/httpx/resolver/system.rb
27 def multi?
28   false
29 end
new(options)
[show source]
   # File lib/httpx/resolver/system.rb
34 def initialize(options)
35   super(0, options)
36   @resolver_options = @options.resolver_options
37   resolv_options = @resolver_options.dup
38   timeouts = resolv_options.delete(:timeouts) || Resolver::RESOLVE_TIMEOUT
39   @_timeouts = Array(timeouts)
40   @timeouts = Hash.new { |tims, host| tims[host] = @_timeouts.dup }
41   resolv_options.delete(:cache)
42   @queries = []
43   @ips = []
44   @pipe_mutex = Thread::Mutex.new
45   @state = :idle
46 end

Public Instance methods

call()
[show source]
   # File lib/httpx/resolver/system.rb
82 def call
83   case @state
84   when :open
85     consume
86   end
87   nil
88 end
close()
[show source]
   # File lib/httpx/resolver/system.rb
62 def close
63   transition(:closed)
64 end
closed?()
[show source]
   # File lib/httpx/resolver/system.rb
74 def closed?
75   @state == :closed
76 end
early_resolve(connection, **)
[show source]
    # File lib/httpx/resolver/system.rb
119 def early_resolve(connection, **); end
empty?()
[show source]
   # File lib/httpx/resolver/system.rb
58 def empty?
59   @connections.empty?
60 end
force_close(*)
[show source]
   # File lib/httpx/resolver/system.rb
66 def force_close(*)
67   close
68   @queries.clear
69   @timeouts.clear
70   @ips.clear
71   super
72 end
handle_socket_timeout(interval)
[show source]
    # File lib/httpx/resolver/system.rb
121 def handle_socket_timeout(interval)
122   error = HTTPX::ResolveTimeoutError.new(interval, "timed out while waiting on select")
123   error.set_backtrace(caller)
124   @queries.each do |_, connection| # rubocop:disable Style/HashEachMethods
125     emit_resolve_error(connection, connection.peer.host, error) if @connections.delete(connection)
126   end
127 
128   while (connection = @connections.shift)
129     emit_resolve_error(connection, connection.peer.host, error)
130   end
131 
132   close_or_resolve
133 end
interests()
[show source]
   # File lib/httpx/resolver/system.rb
90 def interests
91   return if @queries.empty?
92 
93   :r
94 end
lazy_resolve(connection)
[show source]
    # File lib/httpx/resolver/system.rb
110 def lazy_resolve(connection)
111   @connections << connection
112   resolve
113 
114   return if empty?
115 
116   @current_session.select_resolver(self, @current_selector)
117 end
multi()
[show source]
   # File lib/httpx/resolver/system.rb
54 def multi
55   self
56 end
resolvers()
[show source]
   # File lib/httpx/resolver/system.rb
48 def resolvers
49   return enum_for(__method__) unless block_given?
50 
51   yield self
52 end
timeout()
[show source]
    # File lib/httpx/resolver/system.rb
 96 def timeout
 97   _, connection = @queries.first
 98 
 99   return unless connection
100 
101   timeouts = @timeouts[connection.peer.host]
102 
103   return if timeouts.empty?
104 
105   log(level: 2) { "resolver #{FAMILY_TYPES[@record_type]}: next timeout #{timeouts.first} secs... (#{timeouts.size - 1} left)" }
106 
107   timeouts.first
108 end
to_io()
[show source]
   # File lib/httpx/resolver/system.rb
78 def to_io
79   @pipe_read.to_io
80 end