class Mongo::Srv::Resolver

Encapsulates the necessary behavior for querying SRV records as required by the driver.

@api private

Constants

RECORD_PREFIX

@return [ String ] RECORD_PREFIX The prefix prepended to each hostname

before querying SRV records.

Attributes

options[R]

@return [ Hash ] Resolver options.

Public Class Methods

new(**opts) click to toggle source

Creates a new Resolver.

@option opts [ Float ] :timeout The timeout, in seconds, to use for

each DNS record resolution.

@option opts [ Boolean ] :raise_on_invalid Whether or not to raise

an exception if either a record with a mismatched domain is found
or if no records are found. Defaults to true.

@option opts [ Hash ] :resolv_options For internal driver use only.

Options to pass through to Resolv::DNS constructor for SRV lookups.
# File lib/mongo/srv/resolver.rb, line 51
def initialize(**opts)
  @options = opts.freeze
  @resolver = Resolv::DNS.new(@options[:resolv_options])
  @resolver.timeouts = timeout
end

Public Instance Methods

get_records(hostname, srv_service_name=nil, srv_max_hosts=nil) click to toggle source

Obtains all of the SRV records for a given hostname. If a srv_max_hosts is specified and it is greater than 0, return maximum srv_max_hosts records.

In the event that a record with a mismatched domain is found or no records are found, if the :raise_on_invalid option is true, an exception will be raised, otherwise a warning will be logged.

@param [ String ] hostname The hostname whose records should be obtained. @param [ String | nil ] srv_service_name The SRV service name for the DNS query.

If nil, 'mongodb' is used.

@param [ Integer | nil ] srv_max_hosts The maximum number of records to return.

If this value is nil, return all of the records.

@raise [ Mongo::Error::MismatchedDomain ] If the :raise_in_invalid

Resolver option is true and a record with a domain name that does
not match the hostname's is found.

@raise [ Mongo::Error::NoSRVRecords ] If the :raise_in_invalid Resolver

option is true and no records are found.

@return [ Mongo::Srv::Result ] SRV lookup result.

# File lib/mongo/srv/resolver.rb, line 84
def get_records(hostname, srv_service_name=nil, srv_max_hosts=nil)
  query_name = record_prefix(srv_service_name) + hostname
  resources = @resolver.getresources(query_name, Resolv::DNS::Resource::IN::SRV)

  # Collect all of the records into a Result object, raising an error
  # or logging a warning if a record with a mismatched domain is found.
  # Note that in the case a warning is raised, the record is _not_
  # added to the Result object.
  result = Srv::Result.new(hostname)
  resources.each do |record|
    begin
      result.add_record(record)
    rescue Error::MismatchedDomain => e
      if raise_on_invalid?
        raise
      else
        log_warn(e.message)
      end
    end
  end

  # If no records are found, either raise an error or log a warning
  # based on the Resolver's :raise_on_invalid option.
  if result.empty?
    if raise_on_invalid?
      raise Error::NoSRVRecords.new(URI::SRVProtocol::NO_SRV_RECORDS % hostname)
    else
      log_warn(URI::SRVProtocol::NO_SRV_RECORDS % hostname)
    end
  end

  # if srv_max_hosts is in [1, #addresses)
  if (1...result.address_strs.length).include? srv_max_hosts
    sampled_records = resources.shuffle.first(srv_max_hosts)
    result = Srv::Result.new(hostname)
    sampled_records.each { |record| result.add_record(record) }
  end
  result
end
get_txt_options_string(hostname) click to toggle source

Obtains the TXT records of a host.

@param [ String ] hostname The host whose TXT records should be obtained.

@return [ nil | String ] URI options string from TXT record

associated with the hostname, or nil if there is no such record.

@raise [ Mongo::Error::InvalidTXTRecord ] If more than one TXT record is found.

# File lib/mongo/srv/resolver.rb, line 132
def get_txt_options_string(hostname)
  records = @resolver.getresources(hostname, Resolv::DNS::Resource::IN::TXT)
  if records.empty?
    return nil
  end

  if records.length > 1
    msg = "Only one TXT record is allowed: querying hostname #{hostname} returned #{records.length} records"

    raise Error::InvalidTXTRecord, msg
  end

  records[0].strings.join
end
record_prefix(srv_service_name=nil) click to toggle source

Generates the record prefix with a custom SRV service name if it is provided.

@option srv_service_name [ String | nil ] The SRV service name to use

in the record prefix.

@return [ String ] The generated record prefix.

# File lib/mongo/srv/resolver.rb, line 38
def record_prefix(srv_service_name=nil)
  return srv_service_name ? "_#{srv_service_name}._tcp." : RECORD_PREFIX
end
timeout() click to toggle source
# File lib/mongo/srv/resolver.rb, line 60
def timeout
  options[:timeout] || Monitor::DEFAULT_TIMEOUT
end

Private Instance Methods

raise_on_invalid?() click to toggle source

Checks whether an error should be raised due to either a record with a mismatched domain being found or no records being found.

@return [ Boolean ] Whether an error should be raised.

# File lib/mongo/srv/resolver.rb, line 153
def raise_on_invalid?
  @raise_on_invalid ||= @options[:raise_on_invalid] || true
end