lib/mongo/server_selector/base.rb
# Select a server from the specified cluster, taking into account
# mongos pinning for the specified session.
#
# If the session is given and has a pinned server, this server is the
# only server considered for selection. If the server is of type mongos,
# it is returned immediately; otherwise monitoring checks on this
# server are initiated to update its status, and if the server becomes
# a mongos within the server selection timeout, it is returned.
#
# If no session is given or the session does not have a pinned server,
# normal server selection process is performed among all servers in the
# specified cluster matching the preference of this server selector
# object. Monitoring checks are initiated on servers in the cluster until
# a suitable server is found, up to the server selection timeout.
#
# If a suitable server is not found within the server selection timeout,
# this method raises Error::NoServerAvailable.
#
# @param [ Mongo::Cluster ] cluster The cluster from which to select
#   an eligible server.
# @param [ true, false ] ping Whether to ping the server before selection.
#   Deprecated and ignored.
# @param [ Session | nil ] session Optional session to take into account
#   for mongos pinning. Added in version 2.10.0.
#
# @return [ Mongo::Server ] A server matching the server preference.
#
# @raise [ Error::NoServerAvailable ] No server was found matching the
#   specified preference / pinning requirement in the server selection
#   timeout.
# @raise [ Error::LintError ] An unexpected condition was detected, and
#   lint mode is enabled.
#
# @since 2.0.0
Select a server from the specified cluster, taking into account
mongos pinning for the specified session.

If the session is given and has a pinned server, this server is the
only server considered for selection. If the server is of type mongos,
it is returned immediately; otherwise monitoring checks on this
server are initiated to update its status, and if the server becomes
a mongos within the server selection timeout, it is returned.

If no session is given or the session does not have a pinned server,
normal server selection process is performed among all servers in the
specified cluster matching the preference of this server selector
object. Monitoring checks are initiated on servers in the cluster until
a suitable server is found, up to the server selection timeout.

If a suitable server is not found within the server selection timeout,
this method raises Error::NoServerAvailable.
Select a server from the specified cluster taking into account mongos pinning for the specified session . If the session is given and has a pinned server this server is the only server considered for selection . If the server is of type mongos it is returned immediately ; otherwise monitoring checks on this server are initiated to update its status and if the server becomes a mongos within the server selection timeout it is returned . If no session is given or the session does not have a pinned server normal server selection process is performed among all servers in the specified cluster matching the preference of this server selector object . Monitoring checks are initiated on servers in the cluster until a suitable server is found up to the server selection timeout . If a suitable server is not found within the server selection timeout this method raises Error :: NoServerAvailable .
def select_server(cluster, ping = nil, session = nil)
        if cluster.topology.is_a?(Cluster::Topology::LoadBalanced)
          return cluster.servers.first
        end
        server_selection_timeout = cluster.options[:server_selection_timeout] || SERVER_SELECTION_TIMEOUT
        if server_selection_timeout == 0
          msg = "Failing server selection due to zero timeout. " +
            " Requested #{name} in cluster: #{cluster.summary}"
          raise Error::NoServerAvailable.new(self, cluster, msg)
        end
        deadline = Utils.monotonic_time + server_selection_timeout
        if session && session.pinned_server
          if Mongo::Lint.enabled?
            unless cluster.sharded?
              raise Error::LintError, "Session has a pinned server in a non-sharded topology: #{topology}"
            end
          end
          if !session.in_transaction?
            session.unpin
          end
          if server = session.pinned_server
            unless server.mongos?
              while (time_remaining = deadline - Utils.monotonic_time) > 0
                wait_for_server_selection(cluster, time_remaining)
              end
              unless server.mongos?
                msg = "The session being used is pinned to the server which is not a mongos: #{server.summary} " +
                  "(after #{server_selection_timeout} seconds)"
                raise Error::NoServerAvailable.new(self, cluster, msg)
              end
            end
            return server
          end
        end
        if cluster.replica_set?
          validate_max_staleness_value_early!
        end
        if cluster.addresses.empty?
          if Lint.enabled?
            unless cluster.servers.empty?
              raise Error::LintError, "Cluster has no addresses but has servers: #{cluster.servers.map(&:inspect).join(', ')}"
            end
          end
          msg = "Cluster has no addresses, and therefore will never have a server"
          raise Error::NoServerAvailable.new(self, cluster, msg)
        end
        loop do
          server = try_select_server(cluster)
          if server
            unless cluster.topology.compatible?
              raise Error::UnsupportedFeatures, cluster.topology.compatibility_error.to_s
            end
            if session && session.starting_transaction? && cluster.sharded?
              session.pin_to_server(server)
            end
            return server
          end
          cluster.scan!(false)
          time_remaining = deadline - Utils.monotonic_time
          if time_remaining > 0
            wait_for_server_selection(cluster, time_remaining)
          else
            break
          end
        end
        msg = "No #{name} server"
        if is_a?(ServerSelector::Secondary) && !tag_sets.empty?
          msg += " with tag sets: #{tag_sets}"
        end
        msg += " is available in cluster: #{cluster.summary} " +
                "with timeout=#{server_selection_timeout}, " +
                "LT=#{local_threshold_with_cluster(cluster)}"
        msg += server_selection_diagnostic_message(cluster)
        raise Error::NoServerAvailable.new(self, cluster, msg)
      rescue Error::NoServerAvailable => e
        if session && session.in_transaction? && !session.committing_transaction?
          e.add_label('TransientTransactionError')
        end
        if session && session.committing_transaction?
          e.add_label('UnknownTransactionCommitResult')
        end
        raise e
      end
def select_server ( cluster , ping = nil , session = nil ) if cluster . topology . is_a? ( Cluster :: Topology :: LoadBalanced ) return cluster . servers . first end server_selection_timeout = cluster . options [ :server_selection_timeout ] || SERVER_SELECTION_TIMEOUT if server_selection_timeout == 0 msg = "Failing server selection due to zero timeout. " + " Requested #{name} in cluster: #{cluster.summary}" raise Error :: NoServerAvailable . new ( self , cluster , msg ) end deadline = Utils . monotonic_time + server_selection_timeout if session && session . pinned_server if Mongo :: Lint . enabled? unless cluster . sharded? raise Error :: LintError , "Session has a pinned server in a non-sharded topology: #{topology}" end end if ! session . in_transaction? session . unpin end if server = session . pinned_server unless server . mongos? while ( time_remaining = deadline - Utils . monotonic_time ) > 0 wait_for_server_selection ( cluster , time_remaining ) end unless server . mongos? msg = "The session being used is pinned to the server which is not a mongos: #{server.summary} " + "(after #{server_selection_timeout} seconds)" raise Error :: NoServerAvailable . new ( self , cluster , msg ) end end return server end end if cluster . replica_set? validate_max_staleness_value_early! end if cluster . addresses . empty? if Lint . enabled? unless cluster . servers . empty? raise Error :: LintError , "Cluster has no addresses but has servers: #{cluster.servers.map(&:inspect).join(', ')}" end end msg = "Cluster has no addresses, and therefore will never have a server" raise Error :: NoServerAvailable . new ( self , cluster , msg ) end loop do server = try_select_server ( cluster ) if server unless cluster . topology . compatible? raise Error :: UnsupportedFeatures , cluster . topology . compatibility_error . to_s end if session && session . starting_transaction? && cluster . sharded? session . pin_to_server ( server ) end return server end cluster . scan! ( false ) time_remaining = deadline - Utils . monotonic_time if time_remaining > 0 wait_for_server_selection ( cluster , time_remaining ) else break end end msg = "No #{name} server" if is_a? ( ServerSelector :: Secondary ) && ! tag_sets . empty? msg += " with tag sets: #{tag_sets}" end msg += " is available in cluster: #{cluster.summary} " + "with timeout=#{server_selection_timeout}, " + "LT=#{local_threshold_with_cluster(cluster)}" msg += server_selection_diagnostic_message ( cluster ) raise Error :: NoServerAvailable . new ( self , cluster , msg ) rescue Error :: NoServerAvailable => e if session && session . in_transaction? && ! session . committing_transaction? e . add_label ( 'TransientTransactionError' ) end if session && session . committing_transaction? e . add_label ( 'UnknownTransactionCommitResult' ) end raise e end
Select a server from the specified cluster, taking into account
mongos pinning for the specified session.
Select a server from the specified cluster taking into account mongos pinning for the specified session .
# Special handling for zero timeout: if we have to select a server, # and the timeout is zero, fail immediately (since server selection # will take some non-zero amount of time in any case). # Here we assume that a mongos stays in the topology indefinitely. # This will no longer be the case once SRV polling is implemented. =begin Add this check in version 3.0.0
        unless cluster.connected?
          msg = 'Cluster is disconnected'
          raise Error::NoServerAvailable.new(self, cluster, msg)
        end
=end # If we wait for server selection, perform another round of # attempting to locate a suitable server. Otherwise server selection # can raise NoServerAvailable message when the diagnostics # reports an available server of the requested type.
A server matching the server preference.
A server matching the server preference .
 Mongo::Server 
[ Error::NoServerAvailable ] No server was found matching the specified preference / pinning requirement in the server selection timeout.
[ Error :: NoServerAvailable ] No server was found matching the specified preference / pinning requirement in the server selection timeout .
[ Error::LintError ] An unexpected condition was detected, and lint mode is enabled.
[ Error :: LintError ] An unexpected condition was detected and lint mode is enabled .
cluster
<not_specific>
ping
<not_specific>
session
<not_specific>
<not_specific>
session Optional session to take into account for mongos pinning. Added in version 2.10.0.
session Optional session to take into account for mongos pinning . Added in version 2 . 10 . 0 .
since
None