Class: Mongo::ServerSelector::Base

Inherits:
Object
  • Object
show all
Defined in:
lib/mongo/server_selector/base.rb

Overview

Since:

  • 2.0.0

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(options = nil) ⇒ Base

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Initialize the server selector.

Examples:

Initialize the selector.

Mongo::ServerSelector::Secondary.new(:tag_sets => [{'dc' => 'nyc'}])

Initialize the preference with no options.

Mongo::ServerSelector::Secondary.new

Parameters:

  • options (Hash) (defaults to: nil)

    The server preference options.

Options Hash (options):

  • :local_threshold (Integer)

    The local threshold boundary for nearest selection in seconds.

  • :max_staleness (Integer)

    The maximum replication lag, in seconds, that a secondary can suffer and still be eligible for a read. A value of -1 is treated identically to nil, which is to not have a maximum staleness.

  • :hedge (Hash | nil)

    A Hash specifying whether to enable hedged reads on the server. Hedged reads are not enabled by default. When specifying this option, it must be in the format: { enabled: true }, where the value of the :enabled key is a boolean value.

Raises:

Since:

  • 2.0.0



49
50
51
52
53
54
55
56
57
58
59
60
# File 'lib/mongo/server_selector/base.rb', line 49

def initialize(options = nil)
  options = options ? options.dup : {}
  if options[:max_staleness] == -1
    options.delete(:max_staleness)
  end
  @options = options
  @tag_sets = options[:tag_sets] || []
  @max_staleness = options[:max_staleness]
  @hedge = options[:hedge]

  validate!
end

Instance Attribute Details

#hedgeHash | nil (readonly)

Returns hedge The document specifying whether to enable hedged reads.

Returns:

  • (Hash | nil)

    hedge The document specifying whether to enable hedged reads.

Since:

  • 2.0.0



76
77
78
# File 'lib/mongo/server_selector/base.rb', line 76

def hedge
  @hedge
end

#max_stalenessInteger (readonly)

Returns max_staleness The maximum replication lag, in seconds, that a secondary can suffer and still be eligible for a read.

Returns:

  • (Integer)

    max_staleness The maximum replication lag, in seconds, that a secondary can suffer and still be eligible for a read.

Since:

  • 2.4.0



72
73
74
# File 'lib/mongo/server_selector/base.rb', line 72

def max_staleness
  @max_staleness
end

#optionsHash (readonly)

Returns options The options.

Returns:

  • (Hash)

    options The options.

Since:

  • 2.0.0



63
64
65
# File 'lib/mongo/server_selector/base.rb', line 63

def options
  @options
end

#tag_setsArray (readonly)

Returns tag_sets The tag sets used to select servers.

Returns:

  • (Array)

    tag_sets The tag sets used to select servers.

Since:

  • 2.0.0



66
67
68
# File 'lib/mongo/server_selector/base.rb', line 66

def tag_sets
  @tag_sets
end

Instance Method Details

#==(other) ⇒ true, false

Check equality of two server selectors.

Examples:

Check server selector equality.

preference == other

Parameters:

  • other (Object)

    The other preference.

Returns:

  • (true, false)

    Whether the objects are equal.

Since:

  • 2.0.0



136
137
138
139
# File 'lib/mongo/server_selector/base.rb', line 136

def ==(other)
  name == other.name && hedge == other.hedge &&
    max_staleness == other.max_staleness && tag_sets == other.tag_sets
end

#candidates(cluster) ⇒ Array<Server>

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns servers of acceptable types from the cluster.

Does not perform staleness validation, staleness filtering or latency filtering.

Parameters:

  • cluster (Cluster)

    The cluster.

Returns:

  • (Array<Server>)

    The candidate servers.

Since:

  • 2.0.0



403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
# File 'lib/mongo/server_selector/base.rb', line 403

def candidates(cluster)
  servers = cluster.servers
  servers.each do |server|
    validate_max_staleness_support!(server)
  end
  if cluster.single?
    servers
  elsif cluster.sharded?
    servers
  elsif cluster.replica_set?
    select_in_replica_set(servers)
  else
    # Unknown cluster - no servers
    []
  end
end

#inspectString

Inspect the server selector.

Examples:

Inspect the server selector.

selector.inspect

Returns:

  • (String)

    The inspection.

Since:

  • 2.2.0



122
123
124
# File 'lib/mongo/server_selector/base.rb', line 122

def inspect
  "#<#{self.class.name}:0x#{object_id} tag_sets=#{tag_sets.inspect} max_staleness=#{max_staleness.inspect} hedge=#{hedge}>"
end

#local_thresholdFloat

Deprecated.

This setting is now taken from the cluster options when a server is selected. Will be removed in version 3.0.

Get the local threshold boundary for nearest selection in seconds.

Examples:

Get the local threshold.

selector.local_threshold

Returns:

  • (Float)

    The local threshold.

Since:

  • 2.0.0



105
106
107
# File 'lib/mongo/server_selector/base.rb', line 105

def local_threshold
  @local_threshold ||= (options[:local_threshold] || ServerSelector::LOCAL_THRESHOLD)
end

#local_threshold_with_cluster(cluster) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Since:

  • 2.0.0



110
111
112
# File 'lib/mongo/server_selector/base.rb', line 110

def local_threshold_with_cluster(cluster)
  options[:local_threshold] || cluster.options[:local_threshold] || LOCAL_THRESHOLD
end

#select_server(cluster, ping = nil, session = nil, write_aggregation: false, deprioritized: [], timeout: nil) ⇒ Mongo::Server

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.

Parameters:

  • cluster (Mongo::Cluster)

    The cluster from which to select an eligible server.

  • ping (true, false) (defaults to: nil)

    Whether to ping the server before selection. Deprecated and ignored.

  • session (Session | nil) (defaults to: nil)

    Optional session to take into account for mongos pinning. Added in version 2.10.0.

  • write_aggregation (true | false) (defaults to: false)

    Whether we need a server that supports writing aggregations (e.g. with $merge/$out) on secondaries.

  • deprioritized (Array<Server>) (defaults to: [])

    A list of servers that should be selected from only if no other servers are available. This is used to avoid selecting the same server twice in a row when retrying a command.

  • :timeout (Float | nil)

    Timeout in seconds for the operation, if any.

Returns:

Raises:

  • (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.

Since:

  • 2.0.0



183
184
185
186
187
188
189
190
191
192
193
194
195
196
# File 'lib/mongo/server_selector/base.rb', line 183

def select_server(
  cluster,
  ping = nil,
  session = nil,
  write_aggregation: false,
  deprioritized: [],
  timeout: nil
)
  select_server_impl(cluster, ping, session, write_aggregation, deprioritized, timeout).tap do |server|
    if Lint.enabled? && !server.pool.ready?
      raise Error::LintError, 'Server selector returning a server with a pool which is not ready'
    end
  end
end

#server_selection_timeoutFloat

Deprecated.

This setting is now taken from the cluster options when a server is selected. Will be removed in version 3.0.

Get the timeout for server selection.

Examples:

Get the server selection timeout, in seconds.

selector.server_selection_timeout

Returns:

  • (Float)

    The timeout.

Since:

  • 2.0.0



89
90
91
92
# File 'lib/mongo/server_selector/base.rb', line 89

def server_selection_timeout
  @server_selection_timeout ||=
    (options[:server_selection_timeout] || ServerSelector::SERVER_SELECTION_TIMEOUT)
end

#suitable_servers(cluster) ⇒ Array<Server>

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns servers satisfying the server selector from the cluster.

Parameters:

  • cluster (Cluster)

    The cluster.

Returns:

  • (Array<Server>)

    The suitable servers.

Since:

  • 2.0.0



427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
# File 'lib/mongo/server_selector/base.rb', line 427

def suitable_servers(cluster)
  if cluster.single?
    candidates(cluster)
  elsif cluster.sharded?
    local_threshold = local_threshold_with_cluster(cluster)
    servers = candidates(cluster)
    near_servers(servers, local_threshold)
  elsif cluster.replica_set?
    validate_max_staleness_value!(cluster)
    candidates(cluster)
  else
    # Unknown cluster - no servers
    []
  end
end

#try_select_server(cluster, write_aggregation: false, deprioritized: []) ⇒ Server | nil

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Tries to find a suitable server, returns the server if one is available or nil if there isn’t a suitable server.

Parameters:

  • cluster (Mongo::Cluster)

    The cluster from which to select an eligible server.

  • write_aggregation (true | false) (defaults to: false)

    Whether we need a server that supports writing aggregations (e.g. with $merge/$out) on secondaries.

  • deprioritized (Array<Server>) (defaults to: [])

    A list of servers that should be selected from only if no other servers are available. This is used to avoid selecting the same server twice in a row when retrying a command.

Returns:

  • (Server | nil)

    A suitable server, if one exists.

Since:

  • 2.0.0



352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
# File 'lib/mongo/server_selector/base.rb', line 352

def try_select_server(cluster, write_aggregation: false, deprioritized: [])
  servers = if write_aggregation && cluster.replica_set?
    # 1. Check if ALL servers in cluster support secondary writes.
    is_write_supported = cluster.servers.reduce(true) do |res, server|
      res && server.features.merge_out_on_secondary_enabled?
    end

    if is_write_supported
      # 2. If all servers support secondary writes, we respect read preference.
      suitable_servers(cluster)
    else
      # 3. Otherwise we fallback to primary for replica set.
      [cluster.servers.detect(&:primary?)]
    end
  else
    suitable_servers(cluster)
  end

  # This list of servers may be ordered in a specific way
  # by the selector (e.g. for secondary preferred, the first
  # server may be a secondary and the second server may be primary)
  # and we should take the first server here respecting the order
  server = suitable_server(servers, deprioritized)

  if server
    if Lint.enabled?
      # It is possible for a server to have a nil average RTT here
      # because the ARTT comes from description which may be updated
      # by a background thread while server selection is running.
      # Currently lint mode is not a public feature, if/when this
      # changes (https://jira.mongodb.org/browse/RUBY-1576) the
      # requirement for ARTT to be not nil would need to be removed.
      if server.average_round_trip_time.nil?
        raise Error::LintError, "Server #{server.address} has nil average rtt"
      end
    end
  end

  server
end