mongo 2.10.5 → 2.11.0.rc0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/CONTRIBUTING.md +1 -1
- data/lib/mongo.rb +2 -0
- data/lib/mongo/address.rb +4 -0
- data/lib/mongo/address/validator.rb +99 -0
- data/lib/mongo/auth.rb +7 -2
- data/lib/mongo/auth/user.rb +1 -7
- data/lib/mongo/background_thread.rb +135 -0
- data/lib/mongo/bulk_write/transformable.rb +3 -3
- data/lib/mongo/client.rb +74 -16
- data/lib/mongo/cluster.rb +193 -41
- data/lib/mongo/cluster/periodic_executor.rb +31 -43
- data/lib/mongo/cluster/sdam_flow.rb +26 -3
- data/lib/mongo/cluster/srv_monitor.rb +127 -0
- data/lib/mongo/collection/view/readable.rb +3 -5
- data/lib/mongo/collection/view/writable.rb +3 -3
- data/lib/mongo/cursor/builder/get_more_command.rb +1 -4
- data/lib/mongo/cursor/builder/kill_cursors_command.rb +5 -23
- data/lib/mongo/cursor/builder/op_get_more.rb +2 -2
- data/lib/mongo/cursor/builder/op_kill_cursors.rb +5 -24
- data/lib/mongo/error.rb +1 -0
- data/lib/mongo/error/auth_error.rb +1 -1
- data/lib/mongo/error/connection_check_out_timeout.rb +7 -8
- data/lib/mongo/error/invalid_address.rb +24 -0
- data/lib/mongo/error/notable.rb +2 -2
- data/lib/mongo/error/operation_failure.rb +3 -3
- data/lib/mongo/error/pool_closed_error.rb +11 -4
- data/lib/mongo/event.rb +1 -1
- data/lib/mongo/grid/file.rb +0 -5
- data/lib/mongo/grid/file/chunk.rb +0 -2
- data/lib/mongo/grid/fs_bucket.rb +13 -15
- data/lib/mongo/grid/stream/write.rb +3 -9
- data/lib/mongo/loggable.rb +5 -1
- data/lib/mongo/monitoring.rb +1 -0
- data/lib/mongo/monitoring/event/cmap/connection_check_out_failed.rb +7 -0
- data/lib/mongo/monitoring/event/cmap/connection_checked_in.rb +11 -3
- data/lib/mongo/monitoring/event/cmap/connection_checked_out.rb +11 -3
- data/lib/mongo/monitoring/event/cmap/pool_closed.rb +11 -3
- data/lib/mongo/monitoring/event/cmap/pool_created.rb +12 -3
- data/lib/mongo/monitoring/unified_sdam_log_subscriber.rb +62 -0
- data/lib/mongo/operation/shared/executable.rb +5 -10
- data/lib/mongo/operation/shared/sessions_supported.rb +1 -5
- data/lib/mongo/protocol/get_more.rb +1 -2
- data/lib/mongo/protocol/kill_cursors.rb +13 -6
- data/lib/mongo/protocol/serializers.rb +4 -20
- data/lib/mongo/retryable.rb +9 -34
- data/lib/mongo/semaphore.rb +1 -1
- data/lib/mongo/server.rb +113 -42
- data/lib/mongo/server/connection.rb +12 -5
- data/lib/mongo/server/connection_pool.rb +250 -40
- data/lib/mongo/server/connection_pool/populator.rb +58 -0
- data/lib/mongo/server/description.rb +9 -2
- data/lib/mongo/server/monitor.rb +68 -93
- data/lib/mongo/server/monitor/connection.rb +2 -0
- data/lib/mongo/server_selector/selectable.rb +13 -5
- data/lib/mongo/session.rb +0 -13
- data/lib/mongo/srv.rb +17 -0
- data/lib/mongo/srv/monitor.rb +96 -0
- data/lib/mongo/srv/resolver.rb +130 -0
- data/lib/mongo/srv/result.rb +126 -0
- data/lib/mongo/srv/warning_result.rb +35 -0
- data/lib/mongo/uri.rb +45 -55
- data/lib/mongo/uri/srv_protocol.rb +89 -42
- data/lib/mongo/version.rb +1 -1
- data/mongo.gemspec +3 -4
- data/spec/README.md +6 -1
- data/spec/enterprise_auth/kerberos_spec.rb +7 -6
- data/spec/integration/change_stream_examples_spec.rb +0 -4
- data/spec/integration/client_construction_spec.rb +14 -2
- data/spec/integration/connect_single_rs_name_spec.rb +2 -2
- data/spec/integration/connection_pool_populator_spec.rb +296 -0
- data/spec/integration/connection_spec.rb +31 -22
- data/spec/integration/cursor_reaping_spec.rb +1 -2
- data/spec/integration/docs_examples_spec.rb +0 -4
- data/spec/integration/heartbeat_events_spec.rb +17 -15
- data/spec/integration/reconnect_spec.rb +144 -1
- data/spec/integration/retryable_writes_errors_spec.rb +0 -4
- data/spec/integration/retryable_writes_spec.rb +36 -36
- data/spec/integration/sdam_error_handling_spec.rb +31 -25
- data/spec/integration/sdam_events_spec.rb +2 -6
- data/spec/integration/server_monitor_spec.rb +28 -0
- data/spec/integration/server_selector_spec.rb +7 -5
- data/spec/integration/srv_monitoring_spec.rb +360 -0
- data/spec/integration/step_down_spec.rb +4 -6
- data/spec/lite_spec_helper.rb +22 -0
- data/spec/mongo/address/validator_spec.rb +51 -0
- data/spec/mongo/auth/cr_spec.rb +1 -29
- data/spec/mongo/auth/ldap_spec.rb +1 -29
- data/spec/mongo/auth/scram/conversation_spec.rb +0 -2
- data/spec/mongo/auth/scram/negotiation_spec.rb +1 -1
- data/spec/mongo/auth/scram_spec.rb +1 -29
- data/spec/mongo/auth/user/view_spec.rb +1 -36
- data/spec/mongo/auth/user_spec.rb +0 -12
- data/spec/mongo/auth/x509_spec.rb +1 -29
- data/spec/mongo/bulk_write_spec.rb +2 -2
- data/spec/mongo/client_construction_spec.rb +56 -15
- data/spec/mongo/client_spec.rb +31 -27
- data/spec/mongo/cluster/periodic_executor_spec.rb +16 -0
- data/spec/mongo/cluster/srv_monitor_spec.rb +214 -0
- data/spec/mongo/cluster/topology/replica_set_spec.rb +16 -11
- data/spec/mongo/cluster/topology/sharded_spec.rb +12 -9
- data/spec/mongo/cluster/topology/single_spec.rb +20 -11
- data/spec/mongo/cluster_spec.rb +45 -29
- data/spec/mongo/collection/view/map_reduce_spec.rb +14 -9
- data/spec/mongo/collection/view/readable_spec.rb +0 -16
- data/spec/mongo/collection_spec.rb +0 -44
- data/spec/mongo/cursor/builder/get_more_command_spec.rb +2 -4
- data/spec/mongo/cursor/builder/op_get_more_spec.rb +2 -4
- data/spec/mongo/cursor_spec.rb +27 -7
- data/spec/mongo/monitoring/event/cmap/connection_checked_in_spec.rb +10 -3
- data/spec/mongo/monitoring/event/cmap/connection_checked_out_spec.rb +10 -3
- data/spec/mongo/monitoring/event/cmap/pool_closed_spec.rb +10 -3
- data/spec/mongo/monitoring/event/cmap/pool_created_spec.rb +10 -3
- data/spec/mongo/operation/delete/op_msg_spec.rb +17 -8
- data/spec/mongo/operation/insert/op_msg_spec.rb +50 -35
- data/spec/mongo/operation/update/op_msg_spec.rb +14 -7
- data/spec/mongo/retryable_spec.rb +52 -31
- data/spec/mongo/server/app_metadata_spec.rb +0 -8
- data/spec/mongo/server/connection_auth_spec.rb +5 -2
- data/spec/mongo/server/connection_pool/populator_spec.rb +101 -0
- data/spec/mongo/server/connection_pool_spec.rb +256 -107
- data/spec/mongo/server/connection_spec.rb +22 -33
- data/spec/mongo/server/description_spec.rb +42 -4
- data/spec/mongo/server/monitor/connection_spec.rb +22 -11
- data/spec/mongo/server/monitor_spec.rb +66 -107
- data/spec/mongo/server_spec.rb +82 -60
- data/spec/mongo/session/session_pool_spec.rb +1 -5
- data/spec/mongo/session_spec.rb +0 -4
- data/spec/mongo/socket/ssl_spec.rb +2 -2
- data/spec/mongo/srv/monitor_spec.rb +211 -0
- data/spec/mongo/srv/result_spec.rb +54 -0
- data/spec/mongo/uri/srv_protocol_spec.rb +30 -15
- data/spec/mongo/uri_spec.rb +125 -4
- data/spec/spec_helper.rb +6 -0
- data/spec/spec_tests/auth_spec.rb +39 -0
- data/spec/spec_tests/cmap_spec.rb +55 -8
- data/spec/spec_tests/connection_string_spec.rb +6 -31
- data/spec/spec_tests/data/auth/connection-string.yml +297 -0
- data/spec/spec_tests/data/cmap/pool-checkout-error-closed.yml +4 -1
- data/spec/spec_tests/data/cmap/pool-create-with-options.yml +1 -0
- data/spec/spec_tests/data/command_monitoring/insertMany.yml +1 -1
- data/spec/spec_tests/data/connection_string/invalid-uris.yml +20 -0
- data/spec/spec_tests/data/connection_string/valid-auth.yml +16 -0
- data/spec/spec_tests/data/connection_string/valid-warnings.yml +26 -30
- data/spec/spec_tests/data/transactions/abort.yml +3 -3
- data/spec/spec_tests/data/transactions/error-labels.yml +3 -3
- data/spec/spec_tests/data/transactions_api/callback-retry.yml +3 -3
- data/spec/spec_tests/data/uri_options/auth-options.yml +1 -1
- data/spec/spec_tests/max_staleness_spec.rb +7 -2
- data/spec/spec_tests/retryable_reads_spec.rb +0 -31
- data/spec/spec_tests/sdam_monitoring_spec.rb +12 -12
- data/spec/spec_tests/sdam_spec.rb +4 -7
- data/spec/spec_tests/server_selection_spec.rb +6 -2
- data/spec/spec_tests/transactions_spec.rb +0 -2
- data/spec/spec_tests/uri_options_spec.rb +4 -2
- data/spec/stress/connection_pool_stress_spec.rb +203 -0
- data/spec/stress/connection_pool_timing_spec.rb +181 -0
- data/spec/support/auth.rb +113 -0
- data/spec/support/background_thread_registry.rb +63 -0
- data/spec/support/client_registry.rb +11 -2
- data/spec/support/cluster_config.rb +65 -46
- data/spec/support/cluster_tools.rb +2 -2
- data/spec/support/cmap.rb +13 -14
- data/spec/support/cmap/verifier.rb +4 -5
- data/spec/support/command_monitoring.rb +0 -5
- data/spec/support/common_shortcuts.rb +101 -1
- data/spec/support/constraints.rb +25 -0
- data/spec/support/dns.rb +13 -0
- data/spec/support/event_subscriber.rb +0 -7
- data/spec/support/json_ext_formatter.rb +5 -1
- data/spec/support/lite_constraints.rb +22 -6
- data/spec/support/local_resource_registry.rb +34 -0
- data/spec/support/sdam_monitoring.rb +115 -0
- data/spec/support/spec_config.rb +20 -6
- data/spec/support/spec_setup.rb +2 -2
- data/spec/support/transactions.rb +1 -1
- data/spec/support/transactions/test.rb +1 -1
- data/spec/support/utils.rb +1 -16
- metadata +685 -659
- metadata.gz.sig +0 -0
- data/lib/mongo/event/description_changed.rb +0 -52
- data/spec/integration/bson_symbol_spec.rb +0 -34
- data/spec/integration/crud_spec.rb +0 -45
- data/spec/integration/get_more_spec.rb +0 -32
- data/spec/integration/grid_fs_bucket_spec.rb +0 -48
- data/spec/integration/retryable_errors_spec.rb +0 -265
- data/spec/integration/size_limit_spec.rb~12e1e9c4f... RUBY-2242 Fix zlib compression (#2021) +0 -98
- data/spec/mongo/cursor/builder/op_kill_cursors_spec.rb +0 -56
- data/spec/runners/sdam/verifier.rb +0 -88
data/lib/mongo/cluster.rb
CHANGED
@@ -93,11 +93,15 @@ module Mongo
|
|
93
93
|
# to clean up server sessions when the cluster is disconnected, and to
|
94
94
|
# to not start the periodic executor. If :monitoring_io is false,
|
95
95
|
# :cleanup automatically defaults to false as well.
|
96
|
+
# @option options [ Float ] :heartbeat_frequency The interval, in seconds,
|
97
|
+
# for the server monitor to refresh its description via ismaster.
|
98
|
+
# @option options [ Hash ] :resolv_options For internal driver use only.
|
99
|
+
# Options to pass through to Resolv::DNS constructor for SRV lookups.
|
96
100
|
#
|
97
101
|
# @since 2.0.0
|
98
102
|
def initialize(seeds, monitoring, options = Options::Redacted.new)
|
99
|
-
if
|
100
|
-
raise ArgumentError, '
|
103
|
+
if seeds.nil?
|
104
|
+
raise ArgumentError, 'Seeds cannot be nil'
|
101
105
|
end
|
102
106
|
|
103
107
|
if options[:monitoring_io] == false && !options.key?(:cleanup)
|
@@ -105,8 +109,6 @@ module Mongo
|
|
105
109
|
options[:cleanup] = false
|
106
110
|
end
|
107
111
|
|
108
|
-
seeds = seeds.uniq
|
109
|
-
|
110
112
|
@servers = []
|
111
113
|
@monitoring = monitoring
|
112
114
|
@event_listeners = Event::Listeners.new
|
@@ -116,6 +118,8 @@ module Mongo
|
|
116
118
|
@sdam_flow_lock = Mutex.new
|
117
119
|
@cluster_time = nil
|
118
120
|
@cluster_time_lock = Mutex.new
|
121
|
+
@srv_monitor_lock = Mutex.new
|
122
|
+
@server_selection_semaphore = Semaphore.new
|
119
123
|
@topology = Topology.initial(self, monitoring, options)
|
120
124
|
Session::SessionPool.create(self)
|
121
125
|
|
@@ -128,8 +132,6 @@ module Mongo
|
|
128
132
|
Monitoring::Event::TopologyOpening.new(opening_topology)
|
129
133
|
)
|
130
134
|
|
131
|
-
subscribe_to(Event::DESCRIPTION_CHANGED, Event::DescriptionChanged.new(self))
|
132
|
-
|
133
135
|
@seeds = seeds
|
134
136
|
servers = seeds.map do |seed|
|
135
137
|
# Server opening events must be sent after topology change events.
|
@@ -148,27 +150,36 @@ module Mongo
|
|
148
150
|
)
|
149
151
|
end
|
150
152
|
|
151
|
-
servers.each do |server|
|
152
|
-
server.start_monitoring
|
153
|
-
end
|
154
|
-
|
155
153
|
if options[:monitoring_io] == false
|
156
154
|
# Omit periodic executor construction, because without servers
|
157
155
|
# no commands can be sent to the cluster and there shouldn't ever
|
158
156
|
# be anything that needs to be cleaned up.
|
159
157
|
#
|
160
|
-
#
|
161
|
-
# as it would race with tests that mock
|
158
|
+
# Omit monitoring individual servers and the legacy single round of
|
159
|
+
# of SDAM on the main thread, as it would race with tests that mock
|
160
|
+
# SDAM responses.
|
161
|
+
@connecting = @connected = false
|
162
162
|
return
|
163
163
|
end
|
164
164
|
|
165
|
+
# Need to record start time prior to starting monitoring
|
166
|
+
start_time = Time.now
|
167
|
+
|
168
|
+
servers.each do |server|
|
169
|
+
server.start_monitoring
|
170
|
+
end
|
171
|
+
|
165
172
|
if options[:cleanup] != false
|
166
173
|
@cursor_reaper = CursorReaper.new
|
167
174
|
@socket_reaper = SocketReaper.new(self)
|
168
|
-
@periodic_executor = PeriodicExecutor.new(
|
169
|
-
|
175
|
+
@periodic_executor = PeriodicExecutor.new([
|
176
|
+
@cursor_reaper, @socket_reaper,
|
177
|
+
], options)
|
178
|
+
|
179
|
+
ObjectSpace.define_finalizer(self, self.class.finalize(
|
180
|
+
{}, @periodic_executor, @session_pool))
|
170
181
|
|
171
|
-
|
182
|
+
@periodic_executor.run!
|
172
183
|
end
|
173
184
|
|
174
185
|
@connecting = false
|
@@ -184,7 +195,6 @@ module Mongo
|
|
184
195
|
if server_selection_timeout < 3
|
185
196
|
server_selection_timeout = 3
|
186
197
|
end
|
187
|
-
start_time = Time.now
|
188
198
|
deadline = start_time + server_selection_timeout
|
189
199
|
# Wait for the first scan of each server to complete, for
|
190
200
|
# backwards compatibility.
|
@@ -192,16 +202,26 @@ module Mongo
|
|
192
202
|
# wait for these servers to also be queried, and so on, up to the
|
193
203
|
# server selection timeout or the 3 second minimum.
|
194
204
|
loop do
|
195
|
-
servers
|
196
|
-
|
205
|
+
# Ensure we do not try to read the servers list while SDAM is running
|
206
|
+
servers = @sdam_flow_lock.synchronize do
|
207
|
+
servers_list.dup
|
208
|
+
end
|
209
|
+
if servers.all? { |server| server.last_scan && server.last_scan >= start_time }
|
197
210
|
break
|
198
211
|
end
|
199
212
|
if (time_remaining = deadline - Time.now) <= 0
|
200
213
|
break
|
201
214
|
end
|
202
|
-
|
215
|
+
log_debug("Waiting for up to #{'%.2f' % time_remaining} seconds for servers to be scanned: #{summary}")
|
216
|
+
# Since the semaphore may have been signaled between us checking
|
217
|
+
# the servers list above and the wait call below, we should not
|
218
|
+
# wait for the full remaining time - wait for up to 1 second, then
|
219
|
+
# recheck the state.
|
220
|
+
server_selection_semaphore.wait([time_remaining, 1].min)
|
203
221
|
end
|
204
222
|
end
|
223
|
+
|
224
|
+
start_stop_srv_monitor
|
205
225
|
end
|
206
226
|
|
207
227
|
# Create a cluster for the provided client, for use when we don't want the
|
@@ -265,6 +285,9 @@ module Mongo
|
|
265
285
|
end
|
266
286
|
end
|
267
287
|
|
288
|
+
# @api private
|
289
|
+
attr_reader :srv_monitor
|
290
|
+
|
268
291
|
# Get the maximum number of times the client can retry a read operation
|
269
292
|
# when using legacy read retries.
|
270
293
|
#
|
@@ -301,6 +324,17 @@ module Mongo
|
|
301
324
|
options[:read_retry_interval] || READ_RETRY_INTERVAL
|
302
325
|
end
|
303
326
|
|
327
|
+
# Get the refresh interval for the server. This will be defined via an
|
328
|
+
# option or will default to 10.
|
329
|
+
#
|
330
|
+
# @return [ Float ] The heartbeat interval, in seconds.
|
331
|
+
#
|
332
|
+
# @since 2.10.0
|
333
|
+
# @api private
|
334
|
+
def heartbeat_interval
|
335
|
+
options[:heartbeat_frequency] || Server::Monitor::HEARTBEAT_FREQUENCY
|
336
|
+
end
|
337
|
+
|
304
338
|
# Whether the cluster object is connected to its cluster.
|
305
339
|
#
|
306
340
|
# @return [ true|false ] Whether the cluster is connected.
|
@@ -369,9 +403,7 @@ module Mongo
|
|
369
403
|
end
|
370
404
|
|
371
405
|
# @api private
|
372
|
-
|
373
|
-
options[:server_selection_semaphore]
|
374
|
-
end
|
406
|
+
attr_reader :server_selection_semaphore
|
375
407
|
|
376
408
|
# Finalize the cluster for garbage collection.
|
377
409
|
#
|
@@ -392,34 +424,35 @@ module Mongo
|
|
392
424
|
end
|
393
425
|
end
|
394
426
|
|
395
|
-
#
|
427
|
+
# Closes the cluster.
|
396
428
|
#
|
397
429
|
# @note Applications should call Client#close to disconnect from
|
398
430
|
# the cluster rather than calling this method. This method is for
|
399
431
|
# internal driver use only.
|
400
432
|
#
|
401
|
-
#
|
402
|
-
#
|
403
|
-
#
|
404
|
-
# @param [ Boolean ] wait Whether to wait for background threads to
|
405
|
-
# finish running.
|
433
|
+
# Disconnects all servers in the cluster, publishing appropriate SDAM
|
434
|
+
# events in the process. Stops SRV monitoring if it is active.
|
435
|
+
# Marks the cluster disconnected.
|
406
436
|
#
|
407
437
|
# @return [ true ] Always true.
|
408
438
|
#
|
409
439
|
# @since 2.1.0
|
410
|
-
def disconnect!
|
440
|
+
def disconnect!
|
411
441
|
unless @connecting || @connected
|
412
442
|
return true
|
413
443
|
end
|
414
444
|
if options[:cleanup] != false
|
415
|
-
|
416
|
-
|
445
|
+
session_pool.end_sessions
|
446
|
+
@periodic_executor.stop!
|
447
|
+
end
|
448
|
+
@srv_monitor_lock.synchronize do
|
449
|
+
if @srv_monitor
|
450
|
+
@srv_monitor.stop!
|
417
451
|
end
|
418
|
-
@periodic_executor.stop!(wait)
|
419
452
|
end
|
420
453
|
@servers.each do |server|
|
421
454
|
if server.connected?
|
422
|
-
server.disconnect!
|
455
|
+
server.disconnect!
|
423
456
|
publish_sdam_event(
|
424
457
|
Monitoring::SERVER_CLOSED,
|
425
458
|
Monitoring::Event::ServerClosed.new(server.address, topology)
|
@@ -481,16 +514,106 @@ module Mongo
|
|
481
514
|
def scan!(sync=true)
|
482
515
|
if sync
|
483
516
|
servers_list.each do |server|
|
484
|
-
server.
|
517
|
+
if server.monitor
|
518
|
+
server.monitor.scan!
|
519
|
+
else
|
520
|
+
log_warn("Synchronous scan requested on cluster #{summary} but server #{server} has no monitor")
|
521
|
+
end
|
485
522
|
end
|
486
523
|
else
|
487
524
|
servers_list.each do |server|
|
488
|
-
server.
|
525
|
+
server.scan_semaphore.signal
|
489
526
|
end
|
490
527
|
end
|
491
528
|
true
|
492
529
|
end
|
493
530
|
|
531
|
+
# Runs SDAM flow on the cluster.
|
532
|
+
#
|
533
|
+
# This method can be invoked to process a new server description returned
|
534
|
+
# by the server on a monitoring or non-monitoring connection, and also
|
535
|
+
# by the driver when it marks a server unknown as a result of a (network)
|
536
|
+
# error.
|
537
|
+
#
|
538
|
+
# @param [ Server::Description ] previous_desc Previous server description.
|
539
|
+
# @param [ Server::Description ] updated_desc The changed description.
|
540
|
+
# @param [ Hash ] options Options.
|
541
|
+
#
|
542
|
+
# @option options [ true | false ] :keep_connection_pool Usually when the
|
543
|
+
# new server description is unknown, the connection pool on the
|
544
|
+
# respective server is cleared. Set this option to true to keep the
|
545
|
+
# existing connection pool (required when handling not master errors
|
546
|
+
# on 4.2+ servers).
|
547
|
+
#
|
548
|
+
# @api private
|
549
|
+
def run_sdam_flow(previous_desc, updated_desc, options = {})
|
550
|
+
@sdam_flow_lock.synchronize do
|
551
|
+
flow = SdamFlow.new(self, previous_desc, updated_desc)
|
552
|
+
flow.server_description_changed
|
553
|
+
|
554
|
+
# SDAM flow may alter the updated description - grab the final
|
555
|
+
# version for the purposes of broadcasting if a server is available
|
556
|
+
updated_desc = flow.updated_desc
|
557
|
+
|
558
|
+
unless options[:keep_connection_pool]
|
559
|
+
if flow.became_unknown?
|
560
|
+
servers_list.each do |server|
|
561
|
+
if server.address == updated_desc.address
|
562
|
+
server.clear_connection_pool
|
563
|
+
end
|
564
|
+
end
|
565
|
+
end
|
566
|
+
end
|
567
|
+
|
568
|
+
start_stop_srv_monitor
|
569
|
+
end
|
570
|
+
|
571
|
+
# Some updated descriptions, e.g. a mismatched me one, result in the
|
572
|
+
# server whose description we are processing being removed from
|
573
|
+
# the topology. When this happens, the server's monitoring thread gets
|
574
|
+
# killed. As a result, any code after the flow invocation may not run
|
575
|
+
# a particular monitor instance, hence there should generally not be
|
576
|
+
# any code in this method past the flow invocation.
|
577
|
+
#
|
578
|
+
# However, this broadcast call can be here because if the monitoring
|
579
|
+
# thread got killed the server should have been closed and no client
|
580
|
+
# should be currently waiting for it, thus not signaling the semaphore
|
581
|
+
# shouldn't cause any problems.
|
582
|
+
unless updated_desc.unknown?
|
583
|
+
server_selection_semaphore.broadcast
|
584
|
+
end
|
585
|
+
end
|
586
|
+
|
587
|
+
# Sets the list of servers to the addresses in the provided list of address
|
588
|
+
# strings.
|
589
|
+
#
|
590
|
+
# This method is called by the SRV monitor after receiving new DNS records
|
591
|
+
# for the monitored hostname.
|
592
|
+
#
|
593
|
+
# Removes servers in the cluster whose addresses are not in the passed
|
594
|
+
# list of server addresses, and adds servers for any addresses in the
|
595
|
+
# argument which are not already in the cluster.
|
596
|
+
#
|
597
|
+
# @param [ Array<String> ] server_address_strs List of server addresses
|
598
|
+
# to sync the cluster servers to.
|
599
|
+
#
|
600
|
+
# @api private
|
601
|
+
def set_server_list(server_address_strs)
|
602
|
+
@sdam_flow_lock.synchronize do
|
603
|
+
server_address_strs.each do |address_str|
|
604
|
+
unless servers_list.any? { |server| server.address.seed == address_str }
|
605
|
+
add(address_str)
|
606
|
+
end
|
607
|
+
end
|
608
|
+
|
609
|
+
servers_list.each do |server|
|
610
|
+
unless server_address_strs.any? { |address_str| server.address.seed == address_str }
|
611
|
+
remove(server.address.seed)
|
612
|
+
end
|
613
|
+
end
|
614
|
+
end
|
615
|
+
end
|
616
|
+
|
494
617
|
# Determine if this cluster of servers is equal to another object. Checks the
|
495
618
|
# servers currently in the cluster, not what was configured.
|
496
619
|
#
|
@@ -504,9 +627,7 @@ module Mongo
|
|
504
627
|
# @since 2.0.0
|
505
628
|
def ==(other)
|
506
629
|
return false unless other.is_a?(Cluster)
|
507
|
-
addresses == other.addresses &&
|
508
|
-
options.merge(server_selection_semaphore: nil) ==
|
509
|
-
other.options.merge(server_selection_semaphore: nil)
|
630
|
+
addresses == other.addresses && options == other.options
|
510
631
|
end
|
511
632
|
|
512
633
|
# Determine if the cluster would select a readable server for the
|
@@ -657,9 +778,6 @@ module Mongo
|
|
657
778
|
@update_lock.synchronize { @servers.dup }
|
658
779
|
end
|
659
780
|
|
660
|
-
# @api private
|
661
|
-
attr_reader :sdam_flow_lock
|
662
|
-
|
663
781
|
private
|
664
782
|
|
665
783
|
# If options[:session] is set, validates that session and returns it.
|
@@ -706,7 +824,41 @@ module Mongo
|
|
706
824
|
false
|
707
825
|
end
|
708
826
|
end
|
827
|
+
|
828
|
+
# @api private
|
829
|
+
def start_stop_srv_monitor
|
830
|
+
# SRV URI is either always given or not for a given cluster, if one
|
831
|
+
# wasn't given we shouldn't ever have an SRV monitor to manage.
|
832
|
+
return unless options[:srv_uri]
|
833
|
+
|
834
|
+
if topology.is_a?(Topology::Sharded) || topology.is_a?(Topology::Unknown)
|
835
|
+
# Start SRV monitor
|
836
|
+
@srv_monitor_lock.synchronize do
|
837
|
+
unless @srv_monitor
|
838
|
+
monitor_options = options.merge(
|
839
|
+
timeout: options[:connect_timeout] || Server::CONNECT_TIMEOUT)
|
840
|
+
@srv_monitor = _srv_monitor = SrvMonitor.new(self, monitor_options)
|
841
|
+
finalizer = lambda do
|
842
|
+
_srv_monitor.stop!
|
843
|
+
end
|
844
|
+
ObjectSpace.define_finalizer(self, finalizer)
|
845
|
+
end
|
846
|
+
@srv_monitor.run!
|
847
|
+
end
|
848
|
+
else
|
849
|
+
# Stop SRV monitor if running. This path is taken when the client
|
850
|
+
# is given an SRV URI to a standalone/replica set; when the topology
|
851
|
+
# is discovered, since it's not a sharded cluster, the SRV monitor
|
852
|
+
# needs to be stopped.
|
853
|
+
@srv_monitor_lock.synchronize do
|
854
|
+
if @srv_monitor
|
855
|
+
@srv_monitor.stop!
|
856
|
+
end
|
857
|
+
end
|
858
|
+
end
|
859
|
+
end
|
709
860
|
end
|
710
861
|
end
|
711
862
|
|
712
863
|
require 'mongo/cluster/sdam_flow'
|
864
|
+
require 'mongo/cluster/srv_monitor'
|
@@ -22,6 +22,7 @@ module Mongo
|
|
22
22
|
#
|
23
23
|
# @since 2.5.0
|
24
24
|
class PeriodicExecutor
|
25
|
+
include BackgroundThread
|
25
26
|
|
26
27
|
# The default time interval for the periodic executor to execute.
|
27
28
|
#
|
@@ -31,47 +32,43 @@ module Mongo
|
|
31
32
|
# Create a periodic executor.
|
32
33
|
#
|
33
34
|
# @example Create a PeriodicExecutor.
|
34
|
-
# Mongo::Cluster::PeriodicExecutor.new(reaper, reaper2)
|
35
|
+
# Mongo::Cluster::PeriodicExecutor.new([reaper, reaper2])
|
36
|
+
# @param [ Hash ] options The options.
|
37
|
+
#
|
38
|
+
# @option options [ Logger ] :logger A custom logger to use.
|
35
39
|
#
|
36
40
|
# @api private
|
37
41
|
#
|
38
42
|
# @since 2.5.0
|
39
|
-
def initialize(
|
43
|
+
def initialize(executors = [], options = {})
|
40
44
|
@thread = nil
|
41
45
|
@executors = executors
|
46
|
+
@stop_semaphore = Semaphore.new
|
47
|
+
@options = options
|
42
48
|
end
|
43
49
|
|
44
|
-
|
45
|
-
|
46
|
-
# @example Start the periodic executor's thread.
|
47
|
-
# periodic_executor.run!
|
48
|
-
#
|
49
|
-
# @api private
|
50
|
-
#
|
51
|
-
# @since 2.5.0
|
52
|
-
def run!
|
53
|
-
@thread && @thread.alive? ? @thread : start!
|
54
|
-
end
|
50
|
+
attr_reader :options
|
51
|
+
|
55
52
|
alias :restart! :run!
|
56
53
|
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
begin
|
70
|
-
|
71
|
-
|
72
|
-
@thread.join
|
54
|
+
def do_work
|
55
|
+
execute
|
56
|
+
@stop_semaphore.wait(FREQUENCY)
|
57
|
+
end
|
58
|
+
|
59
|
+
def pre_stop
|
60
|
+
@stop_semaphore.signal
|
61
|
+
end
|
62
|
+
|
63
|
+
def stop(final = false)
|
64
|
+
super
|
65
|
+
|
66
|
+
begin
|
67
|
+
flush
|
68
|
+
rescue
|
73
69
|
end
|
74
|
-
|
70
|
+
|
71
|
+
true
|
75
72
|
end
|
76
73
|
|
77
74
|
# Trigger an execute call on each reaper.
|
@@ -83,7 +80,8 @@ module Mongo
|
|
83
80
|
#
|
84
81
|
# @since 2.5.0
|
85
82
|
def execute
|
86
|
-
@executors.each(&:execute)
|
83
|
+
@executors.each(&:execute)
|
84
|
+
true
|
87
85
|
end
|
88
86
|
|
89
87
|
# Execute all pending operations.
|
@@ -95,18 +93,8 @@ module Mongo
|
|
95
93
|
#
|
96
94
|
# @since 2.5.0
|
97
95
|
def flush
|
98
|
-
@executors.each(&:flush)
|
99
|
-
|
100
|
-
|
101
|
-
private
|
102
|
-
|
103
|
-
def start!
|
104
|
-
@thread = Thread.new(FREQUENCY) do |i|
|
105
|
-
loop do
|
106
|
-
sleep(i)
|
107
|
-
execute
|
108
|
-
end
|
109
|
-
end
|
96
|
+
@executors.each(&:flush)
|
97
|
+
true
|
110
98
|
end
|
111
99
|
end
|
112
100
|
end
|