Class: Mongo::ServerSelector::Base
- Inherits:
-
Object
- Object
- Mongo::ServerSelector::Base
- Defined in:
- build/ruby-driver-v2.17/lib/mongo/server_selector/base.rb
Overview
Direct Known Subclasses
Nearest, Primary, PrimaryPreferred, Secondary, SecondaryPreferred
Instance Attribute Summary collapse
-
#hedge ⇒ Hash | nil
readonly
Hedge The document specifying whether to enable hedged reads.
-
#max_staleness ⇒ Integer
readonly
Max_staleness The maximum replication lag, in seconds, that a secondary can suffer and still be eligible for a read.
-
#options ⇒ Hash
readonly
Options The options.
-
#tag_sets ⇒ Array
readonly
Tag_sets The tag sets used to select servers.
Instance Method Summary collapse
-
#==(other) ⇒ true, false
Check equality of two server selectors.
-
#candidates(cluster) ⇒ Array<Server>
private
Returns servers of acceptable types from the cluster.
-
#initialize(options = nil) ⇒ Base
constructor
private
Initialize the server selector.
-
#inspect ⇒ String
Inspect the server selector.
-
#local_threshold ⇒ Float
deprecated
Deprecated.
This setting is now taken from the cluster options when a server is selected. Will be removed in version 3.0.
- #local_threshold_with_cluster(cluster) ⇒ Object private
-
#select_server(cluster, ping = nil, session = nil, write_aggregation: false) ⇒ Mongo::Server
Select a server from the specified cluster, taking into account mongos pinning for the specified session.
-
#server_selection_timeout ⇒ Float
deprecated
Deprecated.
This setting is now taken from the cluster options when a server is selected. Will be removed in version 3.0.
-
#suitable_servers(cluster) ⇒ Array<Server>
private
Returns servers satisfying the server selector from the cluster.
-
#try_select_server(cluster, write_aggregation: false) ⇒ Server | nil
private
Tries to find a suitable server, returns the server if one is available or nil if there isn’t a suitable server.
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.
49 50 51 52 53 54 55 56 57 58 59 60 |
# File 'build/ruby-driver-v2.17/lib/mongo/server_selector/base.rb', line 49 def initialize( = nil) = ? .dup : {} if [:max_staleness] == -1 .delete(:max_staleness) end @options = @tag_sets = [:tag_sets] || [] @max_staleness = [:max_staleness] @hedge = [:hedge] validate! end |
Instance Attribute Details
#hedge ⇒ Hash | nil (readonly)
Returns hedge The document specifying whether to enable hedged reads.
76 77 78 |
# File 'build/ruby-driver-v2.17/lib/mongo/server_selector/base.rb', line 76 def hedge @hedge end |
#max_staleness ⇒ Integer (readonly)
Returns max_staleness The maximum replication lag, in seconds, that a secondary can suffer and still be eligible for a read.
72 73 74 |
# File 'build/ruby-driver-v2.17/lib/mongo/server_selector/base.rb', line 72 def max_staleness @max_staleness end |
#options ⇒ Hash (readonly)
Returns options The options.
63 64 65 |
# File 'build/ruby-driver-v2.17/lib/mongo/server_selector/base.rb', line 63 def @options end |
#tag_sets ⇒ Array (readonly)
Returns tag_sets The tag sets used to select servers.
66 67 68 |
# File 'build/ruby-driver-v2.17/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.
136 137 138 139 |
# File 'build/ruby-driver-v2.17/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.
358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 |
# File 'build/ruby-driver-v2.17/lib/mongo/server_selector/base.rb', line 358 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 |
#inspect ⇒ String
Inspect the server selector.
122 123 124 |
# File 'build/ruby-driver-v2.17/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_threshold ⇒ Float
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.
105 106 107 |
# File 'build/ruby-driver-v2.17/lib/mongo/server_selector/base.rb', line 105 def local_threshold @local_threshold ||= ([: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.
110 111 112 |
# File 'build/ruby-driver-v2.17/lib/mongo/server_selector/base.rb', line 110 def local_threshold_with_cluster(cluster) [:local_threshold] || cluster.[:local_threshold] || LOCAL_THRESHOLD end |
#select_server(cluster, ping = nil, session = nil, write_aggregation: false) ⇒ 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.
177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 |
# File 'build/ruby-driver-v2.17/lib/mongo/server_selector/base.rb', line 177 def select_server(cluster, ping = nil, session = nil, write_aggregation: false) if cluster.topology.is_a?(Cluster::Topology::LoadBalanced) return cluster.servers.first end server_selection_timeout = cluster.[:server_selection_timeout] || SERVER_SELECTION_TIMEOUT # 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). 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 # Here we assume that a mongos stays in the topology indefinitely. # This will no longer be the case once SRV polling is implemented. 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 =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 loop do server = try_select_server(cluster, write_aggregation: write_aggregation) 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) # 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. 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 += (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 |
#server_selection_timeout ⇒ Float
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.
89 90 91 92 |
# File 'build/ruby-driver-v2.17/lib/mongo/server_selector/base.rb', line 89 def server_selection_timeout @server_selection_timeout ||= ([: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.
382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 |
# File 'build/ruby-driver-v2.17/lib/mongo/server_selector/base.rb', line 382 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) ⇒ 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.
307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 |
# File 'build/ruby-driver-v2.17/lib/mongo/server_selector/base.rb', line 307 def try_select_server(cluster, write_aggregation: false) 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 = servers.first 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 |