Module: Mongo::ServerSelector::Selectable

Included in:
Nearest, Primary, PrimaryPreferred, Secondary, SecondaryPreferred
Defined in:
lib/mongo/server_selector/selectable.rb

Overview

Provides common behavior for filtering a list of servers by server mode or tag set.

Since:

  • 2.0.0

Instance Attribute Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#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



65
66
67
# File 'lib/mongo/server_selector/selectable.rb', line 65

def max_staleness
  @max_staleness
end

#optionsHash (readonly)

Returns options The options.

Returns:

  • (Hash)

    options The options.

Since:

  • 2.0.0



56
57
58
# File 'lib/mongo/server_selector/selectable.rb', line 56

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



59
60
61
# File 'lib/mongo/server_selector/selectable.rb', line 59

def tag_sets
  @tag_sets
end

Instance Method Details

#==(other) ⇒ true, false

Check equality of two server selector.

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



77
78
79
80
81
# File 'lib/mongo/server_selector/selectable.rb', line 77

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

#candidates(cluster) ⇒ Array<Server>

Get the potential candidates to select from the cluster.

Examples:

Get the server candidates.

selectable.candidates(cluster)

Parameters:

  • cluster (Cluster)

    The cluster.

Returns:

  • (Array<Server>)

    The candidate servers.

Since:

  • 2.4.0



228
229
230
231
232
233
234
235
236
237
# File 'lib/mongo/server_selector/selectable.rb', line 228

def candidates(cluster)
  if cluster.single?
    cluster.servers.each { |server| validate_max_staleness_support!(server) }
  elsif cluster.sharded?
    near_servers(cluster.servers).each { |server| validate_max_staleness_support!(server) }
  else
    validate_max_staleness_value!(cluster) unless cluster.unknown?
    select(cluster.servers)
  end
end

#initialize(options = nil) ⇒ Object

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.

Raises:

Since:

  • 2.0.0



44
45
46
47
48
49
50
51
52
53
# File 'lib/mongo/server_selector/selectable.rb', line 44

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

#inspectString

Inspect the server selector.

Examples:

Inspect the server selector.

selector.inspect

Returns:

  • (String)

    The inspection.

Since:

  • 2.2.0



91
92
93
# File 'lib/mongo/server_selector/selectable.rb', line 91

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

#local_thresholdFloat

Deprecated.

This setting is now taken from the cluster options when a server is selected. Will be removed in 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



214
215
216
# File 'lib/mongo/server_selector/selectable.rb', line 214

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

#select_server(cluster, ping = nil) ⇒ Mongo::Server

Select a server from eligible candidates.

Examples:

Select a server from the cluster.

selector.select_server(cluster)

Parameters:

  • cluster (Mongo::Cluster)

    The cluster from which to select an eligible server.

Returns:

Raises:

Since:

  • 2.0.0



105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
# File 'lib/mongo/server_selector/selectable.rb', line 105

def select_server(cluster, ping = nil)
  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
=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
  @local_threshold = cluster.options[:local_threshold] || LOCAL_THRESHOLD
  @server_selection_timeout = cluster.options[:server_selection_timeout] || SERVER_SELECTION_TIMEOUT
  deadline = Time.now + server_selection_timeout
  while (time_remaining = deadline - Time.now) > 0
    servers = candidates(cluster)
    if Lint.enabled?
      servers.each do |server|
        if server.average_round_trip_time.nil?
          raise Error::LintError, "Server #{server.address} has nil average rtt"
        end
      end
    end
    if servers && !servers.compact.empty?
      unless cluster.topology.compatible?
        raise Error::UnsupportedFeatures, cluster.topology.compatibility_error.to_s
      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 = servers.first

      if cluster.topology.single? &&
        cluster.topology.replica_set_name &&
        cluster.topology.replica_set_name != server.description.replica_set_name
      then
        msg = "Cluster topology specifies replica set name #{cluster.topology.replica_set_name}, but the server has replica set name #{server.description.replica_set_name || '<nil>'}"
        raise Error::NoServerAvailable.new(self, cluster, msg)
      end

      return server
    end
    cluster.scan!(false)
    if cluster.server_selection_semaphore
      cluster.server_selection_semaphore.wait(time_remaining)
    else
      if Lint.enabled?
        raise Error::LintError, 'Waiting for server selection without having a server selection semaphore'
      end
      sleep 0.25
    end
  end

  msg = "No #{name} server is available in cluster: #{cluster.summary} " +
          "with timeout=#{server_selection_timeout}, " +
          "LT=#{local_threshold}"
  dead_monitors = []
  cluster.servers_list.each do |server|
    thread = server.monitor.instance_variable_get('@thread')
    if thread.nil? || !thread.alive?
      dead_monitors << server
    end
  end
  if dead_monitors.any?
    msg += ". The following servers have dead monitor threads: #{dead_monitors.map(&:summary).join(', ')}"
  end
  unless cluster.connected?
    msg += ". The cluster is disconnected (client may have been closed)"
  end
  raise Error::NoServerAvailable.new(self, cluster, msg)
end

#server_selection_timeoutFloat

Deprecated.

This setting is now taken from the cluster options when a server is selected. Will be removed in 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



198
199
200
201
# File 'lib/mongo/server_selector/selectable.rb', line 198

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