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
30 def multi?
31   false
32 end
new(options)
[show source]
   # File lib/httpx/resolver/system.rb
37 def initialize(options)
38   super(0, options)
39   @resolver_options = @options.resolver_options
40   resolv_options = @resolver_options.dup
41   timeouts = resolv_options.delete(:timeouts) || Resolver::RESOLVE_TIMEOUT
42   @_timeouts = Array(timeouts)
43   @timeouts = Hash.new { |tims, host| tims[host] = @_timeouts.dup }
44   resolv_options.delete(:cache)
45   @queries = []
46   @ips = []
47   @pipe_mutex = Thread::Mutex.new
48   @state = :idle
49 end

Public Instance methods

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