mongo 2.10.5 → 2.11.0.rc0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|