mongo 2.9.2 → 2.10.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/lib/mongo.rb +1 -0
- data/lib/mongo/auth/user/view.rb +4 -4
- data/lib/mongo/bulk_write.rb +14 -8
- data/lib/mongo/bulk_write/result.rb +1 -1
- data/lib/mongo/bulk_write/result_combiner.rb +2 -2
- data/lib/mongo/bulk_write/transformable.rb +17 -9
- data/lib/mongo/client.rb +107 -16
- data/lib/mongo/cluster.rb +47 -25
- data/lib/mongo/cluster/topology/replica_set_no_primary.rb +1 -1
- data/lib/mongo/cluster_time.rb +139 -0
- data/lib/mongo/collection.rb +84 -25
- data/lib/mongo/collection/view.rb +7 -3
- data/lib/mongo/collection/view/aggregation.rb +4 -4
- data/lib/mongo/collection/view/builder/aggregation.rb +31 -6
- data/lib/mongo/collection/view/builder/find_command.rb +4 -1
- data/lib/mongo/collection/view/builder/map_reduce.rb +4 -1
- data/lib/mongo/collection/view/change_stream.rb +54 -66
- data/lib/mongo/collection/view/iterable.rb +2 -2
- data/lib/mongo/collection/view/map_reduce.rb +6 -4
- data/lib/mongo/collection/view/readable.rb +36 -16
- data/lib/mongo/collection/view/writable.rb +68 -22
- data/lib/mongo/cursor.rb +87 -20
- data/lib/mongo/database.rb +47 -43
- data/lib/mongo/database/view.rb +54 -11
- data/lib/mongo/error.rb +13 -4
- data/lib/mongo/error/invalid_write_concern.rb +2 -2
- data/lib/mongo/error/operation_failure.rb +65 -11
- data/lib/mongo/error/parser.rb +41 -8
- data/lib/mongo/grid/fs_bucket.rb +26 -6
- data/lib/mongo/grid/stream/read.rb +9 -2
- data/lib/mongo/grid/stream/write.rb +21 -5
- data/lib/mongo/index/view.rb +3 -3
- data/lib/mongo/lint.rb +10 -3
- data/lib/mongo/operation.rb +2 -0
- data/lib/mongo/operation/aggregate/result.rb +19 -6
- data/lib/mongo/operation/collections_info.rb +1 -1
- data/lib/mongo/operation/get_more/result.rb +9 -0
- data/lib/mongo/operation/list_collections/command.rb +1 -3
- data/lib/mongo/operation/list_collections/op_msg.rb +1 -2
- data/lib/mongo/operation/parallel_scan/command.rb +4 -1
- data/lib/mongo/operation/parallel_scan/op_msg.rb +4 -1
- data/lib/mongo/operation/result.rb +27 -4
- data/lib/mongo/operation/shared/executable.rb +19 -5
- data/lib/mongo/operation/shared/executable_no_validate.rb +1 -2
- data/lib/mongo/operation/shared/executable_transaction_label.rb +0 -9
- data/lib/mongo/operation/shared/polymorphic_result.rb +9 -1
- data/lib/mongo/operation/shared/result/aggregatable.rb +2 -2
- data/lib/mongo/operation/shared/sessions_supported.rb +42 -32
- data/lib/mongo/operation/shared/specifiable.rb +40 -0
- data/lib/mongo/operation/shared/unpinnable.rb +39 -0
- data/lib/mongo/operation/shared/write.rb +1 -1
- data/lib/mongo/protocol/update.rb +6 -2
- data/lib/mongo/retryable.rb +79 -39
- data/lib/mongo/server/connection.rb +10 -3
- data/lib/mongo/server/description.rb +25 -1
- data/lib/mongo/server/monitor/connection.rb +1 -1
- data/lib/mongo/server_selector.rb +10 -0
- data/lib/mongo/server_selector/selectable.rb +172 -32
- data/lib/mongo/session.rb +654 -581
- data/lib/mongo/session/session_pool.rb +1 -1
- data/lib/mongo/socket.rb +7 -28
- data/lib/mongo/socket/ssl.rb +26 -1
- data/lib/mongo/socket/tcp.rb +3 -0
- data/lib/mongo/socket/unix.rb +3 -0
- data/lib/mongo/uri.rb +112 -265
- data/lib/mongo/uri/srv_protocol.rb +4 -1
- data/lib/mongo/version.rb +1 -1
- data/lib/mongo/write_concern.rb +10 -29
- data/lib/mongo/write_concern/acknowledged.rb +12 -0
- data/lib/mongo/write_concern/base.rb +17 -13
- data/lib/mongo/write_concern/unacknowledged.rb +12 -0
- data/spec/atlas/atlas_connectivity_spec.rb +7 -37
- data/spec/atlas/operations_spec.rb +25 -0
- data/spec/integration/change_stream_examples_spec.rb +45 -31
- data/spec/integration/change_stream_spec.rb +305 -5
- data/spec/integration/client_spec.rb +44 -0
- data/spec/integration/command_monitoring_spec.rb +1 -0
- data/spec/integration/command_spec.rb +7 -1
- data/spec/integration/mmapv1_spec.rb +28 -0
- data/spec/integration/mongos_pinning_spec.rb +34 -0
- data/spec/integration/operation_failure_code_spec.rb +2 -2
- data/spec/integration/{read_concern.rb → read_concern_spec.rb} +7 -1
- data/spec/integration/read_preference_spec.rb +485 -0
- data/spec/integration/retryable_writes_spec.rb +8 -19
- data/spec/integration/sdam_error_handling_spec.rb +1 -1
- data/spec/integration/sdam_events_spec.rb +2 -2
- data/spec/integration/server_description_spec.rb +14 -17
- data/spec/integration/server_selector_spec.rb +7 -3
- data/spec/integration/server_spec.rb +48 -0
- data/spec/integration/ssl_uri_options_spec.rb +1 -1
- data/spec/integration/step_down_spec.rb +10 -4
- data/spec/integration/transactions_examples_spec.rb +11 -10
- data/spec/lite_spec_helper.rb +19 -16
- data/spec/mongo/auth/scram/negotiation_spec.rb +11 -8
- data/spec/mongo/bulk_write/ordered_combiner_spec.rb +6 -6
- data/spec/mongo/bulk_write/unordered_combiner_spec.rb +4 -4
- data/spec/mongo/bulk_write_spec.rb +12 -2
- data/spec/mongo/client_construction_spec.rb +160 -8
- data/spec/mongo/client_spec.rb +5 -4
- data/spec/mongo/cluster_spec.rb +6 -6
- data/spec/mongo/cluster_time_spec.rb +148 -0
- data/spec/mongo/collection/view/aggregation_spec.rb +34 -15
- data/spec/mongo/collection/view/change_stream_spec.rb +62 -3
- data/spec/mongo/collection/view/map_reduce_spec.rb +7 -5
- data/spec/mongo/collection/view/readable_spec.rb +4 -4
- data/spec/mongo/collection_spec.rb +331 -14
- data/spec/mongo/cursor_spec.rb +117 -5
- data/spec/mongo/database_spec.rb +240 -8
- data/spec/mongo/error/operation_failure_spec.rb +47 -1
- data/spec/mongo/error/parser_spec.rb +160 -23
- data/spec/mongo/operation/insert/bulk_spec.rb +2 -1
- data/spec/mongo/operation/result_spec.rb +27 -0
- data/spec/mongo/operation/update/bulk_spec.rb +1 -0
- data/spec/mongo/retryable_spec.rb +2 -0
- data/spec/mongo/server/app_metadata_spec.rb +2 -2
- data/spec/mongo/server/connection_spec.rb +13 -17
- data/spec/mongo/server/monitor/connection_spec.rb +13 -10
- data/spec/mongo/server_selector_spec.rb +34 -2
- data/spec/mongo/session/session_pool_spec.rb +14 -3
- data/spec/mongo/session_spec.rb +3 -3
- data/spec/mongo/session_transaction_spec.rb +4 -3
- data/spec/mongo/socket/ssl_spec.rb +19 -5
- data/spec/mongo/socket_spec.rb +1 -62
- data/spec/mongo/uri/srv_protocol_spec.rb +14 -20
- data/spec/mongo/uri_option_parsing_spec.rb +94 -8
- data/spec/mongo/uri_spec.rb +23 -10
- data/spec/mongo/write_concern_spec.rb +56 -3
- data/spec/spec_tests/change_streams_spec.rb +2 -1
- data/spec/spec_tests/cmap_spec.rb +1 -1
- data/spec/spec_tests/crud_spec.rb +12 -2
- data/spec/spec_tests/data/change_streams/change-streams-errors.yml +24 -1
- data/spec/spec_tests/data/change_streams/change-streams.yml +172 -3
- data/spec/spec_tests/data/command_monitoring/bulkWrite.yml +1 -1
- data/spec/spec_tests/data/command_monitoring/updateMany.yml +0 -2
- data/spec/spec_tests/data/command_monitoring/updateOne.yml +0 -5
- data/spec/spec_tests/data/crud/read/aggregate-out.yml +0 -6
- data/spec/spec_tests/data/crud/read/count-empty.yml +29 -0
- data/spec/spec_tests/data/crud/write/bulkWrite-arrayFilters.yml +1 -0
- data/spec/spec_tests/data/crud/write/bulkWrite-collation.yml +101 -0
- data/spec/spec_tests/data/crud/write/bulkWrite.yml +401 -0
- data/spec/spec_tests/data/crud/write/insertMany.yml +58 -2
- data/spec/spec_tests/data/crud/write/updateMany-arrayFilters.yml +3 -0
- data/spec/spec_tests/data/crud/write/updateOne-arrayFilters.yml +6 -1
- data/spec/spec_tests/data/crud_v2/aggregate-merge.yml +103 -0
- data/spec/spec_tests/data/crud_v2/aggregate-out-readConcern.yml +110 -0
- data/spec/spec_tests/data/crud_v2/bulkWrite-arrayFilters.yml +81 -0
- data/spec/spec_tests/data/crud_v2/db-aggregate.yml +38 -0
- data/spec/spec_tests/data/crud_v2/updateWithPipelines.yml +92 -0
- data/spec/spec_tests/data/retryable_writes/insertOne-serverErrors.yml +2 -2
- data/spec/spec_tests/data/transactions/abort.yml +3 -0
- data/spec/spec_tests/data/transactions/bulk.yml +3 -8
- data/spec/spec_tests/data/transactions/causal-consistency.yml +3 -8
- data/spec/spec_tests/data/transactions/commit.yml +3 -1
- data/spec/spec_tests/data/transactions/count.yml +3 -0
- data/spec/spec_tests/data/transactions/delete.yml +3 -0
- data/spec/spec_tests/data/transactions/error-labels.yml +4 -1
- data/spec/spec_tests/data/transactions/errors-client.yml +56 -0
- data/spec/spec_tests/data/transactions/errors.yml +3 -0
- data/spec/spec_tests/data/transactions/findOneAndDelete.yml +3 -0
- data/spec/spec_tests/data/transactions/findOneAndReplace.yml +3 -0
- data/spec/spec_tests/data/transactions/findOneAndUpdate.yml +3 -0
- data/spec/spec_tests/data/transactions/insert.yml +3 -0
- data/spec/spec_tests/data/transactions/isolation.yml +3 -0
- data/spec/spec_tests/data/transactions/mongos-pin-auto.yml +1671 -0
- data/spec/spec_tests/data/transactions/mongos-recovery-token.yml +347 -0
- data/spec/spec_tests/data/transactions/pin-mongos.yml +557 -0
- data/spec/spec_tests/data/transactions/read-concern.yml +3 -0
- data/spec/spec_tests/data/transactions/read-pref.yml +3 -0
- data/spec/spec_tests/data/transactions/reads.yml +3 -0
- data/spec/spec_tests/data/transactions/retryable-abort.yml +5 -2
- data/spec/spec_tests/data/transactions/retryable-commit.yml +4 -1
- data/spec/spec_tests/data/transactions/retryable-writes.yml +3 -0
- data/spec/spec_tests/data/transactions/run-command.yml +3 -0
- data/spec/spec_tests/data/transactions/transaction-options.yml +6 -0
- data/spec/spec_tests/data/transactions/update.yml +3 -8
- data/spec/spec_tests/data/transactions/write-concern.yml +348 -38
- data/spec/spec_tests/data/transactions_api/callback-aborts.yml +6 -0
- data/spec/spec_tests/data/transactions_api/callback-commits.yml +5 -0
- data/spec/spec_tests/data/transactions_api/callback-retry.yml +7 -2
- data/spec/spec_tests/data/transactions_api/commit-retry.yml +70 -15
- data/spec/spec_tests/data/transactions_api/commit-transienttransactionerror-4.2.yml +3 -0
- data/spec/spec_tests/data/transactions_api/commit-transienttransactionerror.yml +3 -0
- data/spec/spec_tests/data/transactions_api/commit-writeconcernerror.yml +59 -109
- data/spec/spec_tests/data/transactions_api/commit.yml +5 -0
- data/spec/spec_tests/data/transactions_api/transaction-options.yml +10 -0
- data/spec/spec_tests/retryable_reads_spec.rb +5 -2
- data/spec/spec_tests/retryable_writes_spec.rb +5 -2
- data/spec/spec_tests/sdam_monitoring_spec.rb +3 -3
- data/spec/spec_tests/sdam_spec.rb +2 -2
- data/spec/spec_tests/transactions_api_spec.rb +1 -67
- data/spec/spec_tests/transactions_spec.rb +2 -66
- data/spec/support/authorization.rb +4 -0
- data/spec/support/change_streams.rb +30 -10
- data/spec/support/change_streams/operation.rb +27 -0
- data/spec/support/client_registry.rb +44 -25
- data/spec/support/cluster_config.rb +25 -14
- data/spec/support/cluster_tools.rb +32 -10
- data/spec/support/command_monitoring.rb +1 -1
- data/spec/support/common_shortcuts.rb +30 -0
- data/spec/support/connection_string.rb +8 -3
- data/spec/support/constraints.rb +34 -0
- data/spec/support/crud.rb +31 -16
- data/spec/support/crud/context.rb +23 -0
- data/spec/support/crud/operation.rb +311 -14
- data/spec/support/crud/spec.rb +2 -1
- data/spec/support/crud/test.rb +24 -27
- data/spec/support/crud/test_base.rb +22 -0
- data/spec/support/crud/verifier.rb +15 -1
- data/spec/support/event_subscriber.rb +12 -0
- data/spec/support/sdam_formatter_integration.rb +12 -6
- data/spec/support/shared/server_selector.rb +10 -0
- data/spec/support/shared/session.rb +13 -12
- data/spec/support/spec_config.rb +32 -22
- data/spec/support/spec_setup.rb +2 -2
- data/spec/support/transactions.rb +87 -0
- data/spec/support/transactions/context.rb +33 -0
- data/spec/support/transactions/operation.rb +99 -349
- data/spec/support/transactions/spec.rb +1 -3
- data/spec/support/transactions/test.rb +110 -49
- data/spec/support/utils.rb +74 -1
- metadata +52 -10
- metadata.gz.sig +0 -0
- data/spec/support/crud/read.rb +0 -265
- data/spec/support/crud/write.rb +0 -284
data/lib/mongo/cluster.rb
CHANGED
@@ -28,6 +28,7 @@ module Mongo
|
|
28
28
|
include Monitoring::Publishable
|
29
29
|
include Event::Subscriber
|
30
30
|
include Loggable
|
31
|
+
include ClusterTime::Consumer
|
31
32
|
|
32
33
|
# The default number of legacy read retries.
|
33
34
|
#
|
@@ -53,6 +54,7 @@ module Mongo
|
|
53
54
|
# The cluster time key in responses from mongos servers.
|
54
55
|
#
|
55
56
|
# @since 2.5.0
|
57
|
+
# @deprecated
|
56
58
|
CLUSTER_TIME = 'clusterTime'.freeze
|
57
59
|
|
58
60
|
# Instantiate the new cluster.
|
@@ -74,18 +76,23 @@ module Mongo
|
|
74
76
|
# @param [ Hash ] options Options. Client constructor forwards its
|
75
77
|
# options to Cluster constructor, although Cluster recognizes
|
76
78
|
# only a subset of the options recognized by Client.
|
77
|
-
# @option options [ true
|
79
|
+
# @option options [ true | false ] :scan Whether to scan all seeds
|
78
80
|
# in constructor. The default in driver version 2.x is to do so;
|
79
81
|
# driver version 3.x will not scan seeds in constructor. Opt in to the
|
80
82
|
# new behavior by setting this option to false. *Note:* setting
|
81
83
|
# this option to nil enables scanning seeds in constructor in driver
|
82
84
|
# version 2.x. Driver version 3.x will recognize this option but
|
83
85
|
# will ignore it and will never scan seeds in the constructor.
|
84
|
-
# @option options [ true
|
86
|
+
# @option options [ true | false ] :monitoring_io For internal driver
|
85
87
|
# use only. Set to false to prevent SDAM-related I/O from being
|
86
88
|
# done by this cluster or servers under it. Note: setting this option
|
87
89
|
# to false will make the cluster non-functional. It is intended for
|
88
90
|
# use in tests which manually invoke SDAM state transitions.
|
91
|
+
# @option options [ true | false ] :cleanup For internal driver use only.
|
92
|
+
# Set to false to prevent endSessions command being sent to the server
|
93
|
+
# to clean up server sessions when the cluster is disconnected, and to
|
94
|
+
# to not start the periodic executor. If :monitoring_io is false,
|
95
|
+
# :cleanup automatically defaults to false as well.
|
89
96
|
#
|
90
97
|
# @since 2.0.0
|
91
98
|
def initialize(seeds, monitoring, options = Options::Redacted.new)
|
@@ -93,6 +100,11 @@ module Mongo
|
|
93
100
|
raise ArgumentError, 'Need server selection semaphore'
|
94
101
|
end
|
95
102
|
|
103
|
+
if options[:monitoring_io] == false && !options.key?(:cleanup)
|
104
|
+
options = options.dup
|
105
|
+
options[:cleanup] = false
|
106
|
+
end
|
107
|
+
|
96
108
|
@servers = []
|
97
109
|
@monitoring = monitoring
|
98
110
|
@event_listeners = Event::Listeners.new
|
@@ -148,12 +160,14 @@ module Mongo
|
|
148
160
|
return
|
149
161
|
end
|
150
162
|
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
163
|
+
if options[:cleanup] != false
|
164
|
+
@cursor_reaper = CursorReaper.new
|
165
|
+
@socket_reaper = SocketReaper.new(self)
|
166
|
+
@periodic_executor = PeriodicExecutor.new(@cursor_reaper, @socket_reaper)
|
167
|
+
@periodic_executor.run!
|
155
168
|
|
156
|
-
|
169
|
+
ObjectSpace.define_finalizer(self, self.class.finalize({}, @periodic_executor, @session_pool))
|
170
|
+
end
|
157
171
|
|
158
172
|
@connecting = false
|
159
173
|
@connected = true
|
@@ -225,11 +239,6 @@ module Mongo
|
|
225
239
|
# @since 2.4.0
|
226
240
|
attr_reader :app_metadata
|
227
241
|
|
228
|
-
# @return [ BSON::Document ] The latest cluster time seen.
|
229
|
-
#
|
230
|
-
# @since 2.5.0
|
231
|
-
attr_reader :cluster_time
|
232
|
-
|
233
242
|
# @return [ Array<String> ] The addresses of seed servers. Contains
|
234
243
|
# addresses that were given to Cluster when it was instantiated, not
|
235
244
|
# current addresses that the cluster is using as a result of SDAM.
|
@@ -245,7 +254,14 @@ module Mongo
|
|
245
254
|
|
246
255
|
def_delegators :topology, :replica_set?, :replica_set_name, :sharded?,
|
247
256
|
:single?, :unknown?
|
248
|
-
|
257
|
+
|
258
|
+
[:register_cursor, :schedule_kill_cursor, :unregister_cursor].each do |m|
|
259
|
+
define_method(m) do |*args|
|
260
|
+
if options[:cleanup] != false
|
261
|
+
@cursor_reaper.send(m, *args)
|
262
|
+
end
|
263
|
+
end
|
264
|
+
end
|
249
265
|
|
250
266
|
# Get the maximum number of times the client can retry a read operation
|
251
267
|
# when using legacy read retries.
|
@@ -393,7 +409,12 @@ module Mongo
|
|
393
409
|
unless @connecting || @connected
|
394
410
|
return true
|
395
411
|
end
|
396
|
-
|
412
|
+
if options[:cleanup] != false
|
413
|
+
if wait
|
414
|
+
session_pool.end_sessions
|
415
|
+
end
|
416
|
+
@periodic_executor.stop!(wait)
|
417
|
+
end
|
397
418
|
@servers.each do |server|
|
398
419
|
if server.connected?
|
399
420
|
server.disconnect!(wait)
|
@@ -519,16 +540,16 @@ module Mongo
|
|
519
540
|
# @example Get the next primary server.
|
520
541
|
# cluster.next_primary
|
521
542
|
#
|
522
|
-
# @param [ true, false ] ping Whether to ping the server before selection.
|
523
|
-
#
|
524
|
-
#
|
543
|
+
# @param [ true, false ] ping Whether to ping the server before selection.
|
544
|
+
# Deprecated and ignored.
|
545
|
+
# @param [ Session | nil ] session Optional session to take into account
|
546
|
+
# for mongos pinning.
|
525
547
|
#
|
526
548
|
# @return [ Mongo::Server ] A primary server.
|
527
549
|
#
|
528
550
|
# @since 2.0.0
|
529
|
-
def next_primary(ping =
|
530
|
-
|
531
|
-
@primary_selector.select_server(self)
|
551
|
+
def next_primary(ping = nil, session = nil)
|
552
|
+
ServerSelector.primary.select_server(self, nil, session)
|
532
553
|
end
|
533
554
|
|
534
555
|
# Get the connection pool for the server.
|
@@ -559,11 +580,7 @@ module Mongo
|
|
559
580
|
def update_cluster_time(result)
|
560
581
|
if cluster_time_doc = result.cluster_time
|
561
582
|
@cluster_time_lock.synchronize do
|
562
|
-
|
563
|
-
@cluster_time = cluster_time_doc
|
564
|
-
elsif cluster_time_doc[CLUSTER_TIME] > @cluster_time[CLUSTER_TIME]
|
565
|
-
@cluster_time = cluster_time_doc
|
566
|
-
end
|
583
|
+
advance_cluster_time(cluster_time_doc)
|
567
584
|
end
|
568
585
|
end
|
569
586
|
end
|
@@ -670,6 +687,11 @@ module Mongo
|
|
670
687
|
# @note If the cluster has no data bearing servers, for example because
|
671
688
|
# the deployment is in the middle of a failover, this method returns
|
672
689
|
# false.
|
690
|
+
#
|
691
|
+
# @note This method returns as soon as the driver connects to any single
|
692
|
+
# server in the deployment. Whether deployment overall supports sessions
|
693
|
+
# can change depending on how many servers have been contacted, if
|
694
|
+
# the servers are configured differently.
|
673
695
|
def sessions_supported?
|
674
696
|
if topology.data_bearing_servers?
|
675
697
|
return !!topology.logical_session_timeout
|
@@ -74,7 +74,7 @@ module Mongo
|
|
74
74
|
#
|
75
75
|
# @since 2.4.0
|
76
76
|
def has_readable_server?(cluster, server_selector = nil)
|
77
|
-
(server_selector || ServerSelector.
|
77
|
+
(server_selector || ServerSelector.primary).candidates(cluster).any?
|
78
78
|
end
|
79
79
|
|
80
80
|
# Determine if the topology would select a writable server for the
|
@@ -0,0 +1,139 @@
|
|
1
|
+
# Copyright (C) 2019 MongoDB, Inc.
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
|
15
|
+
module Mongo
|
16
|
+
# ClusterTime encapsulates cluster time storage and operations.
|
17
|
+
#
|
18
|
+
# The primary operation performed on the cluster time is advancing it:
|
19
|
+
# given another cluster time, pick the newer of the two.
|
20
|
+
#
|
21
|
+
# This class provides comparison methods that are used to figure out which
|
22
|
+
# cluster time is newer, and provides diagnostics in lint mode when
|
23
|
+
# the actual time is missing from a cluster time document.
|
24
|
+
#
|
25
|
+
# @api private
|
26
|
+
class ClusterTime < BSON::Document
|
27
|
+
def initialize(elements = nil)
|
28
|
+
super
|
29
|
+
|
30
|
+
if Lint.enabled? && !self['clusterTime']
|
31
|
+
raise ArgumentError, 'Creating a cluster time without clusterTime field'
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
# Advances the cluster time in the receiver to the cluster time in +other+.
|
36
|
+
#
|
37
|
+
# +other+ can be nil or be behind the cluster time in the receiver; in
|
38
|
+
# these cases the receiver is returned unmodified. If receiver is advanced,
|
39
|
+
# a new ClusterTime object is returned.
|
40
|
+
#
|
41
|
+
# Return value is nil or a ClusterTime instance.
|
42
|
+
def advance(other)
|
43
|
+
if self['clusterTime'] && other['clusterTime'] &&
|
44
|
+
other['clusterTime'] > self['clusterTime']
|
45
|
+
then
|
46
|
+
ClusterTime[other]
|
47
|
+
else
|
48
|
+
self
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
# Compares two ClusterTime instances by comparing their timestamps.
|
53
|
+
def <=>(other)
|
54
|
+
if self['clusterTime'] && other['clusterTime']
|
55
|
+
self['clusterTime'] <=> other['clusterTime']
|
56
|
+
elsif !self['clusterTime']
|
57
|
+
raise ArgumentError, "Cannot compare cluster times when receiver is missing clusterTime key: #{inspect}"
|
58
|
+
else other['clusterTime']
|
59
|
+
raise ArgumentError, "Cannot compare cluster times when other is missing clusterTime key: #{other.inspect}"
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
# Older Rubies do not implement other logical operators through <=>.
|
64
|
+
# TODO revise whether these methods are needed when
|
65
|
+
# https://jira.mongodb.org/browse/RUBY-1622 is implemented.
|
66
|
+
def >=(other)
|
67
|
+
(self <=> other) != -1
|
68
|
+
end
|
69
|
+
def >(other)
|
70
|
+
(self <=> other) == 1
|
71
|
+
end
|
72
|
+
def <=(other)
|
73
|
+
(self <=> other) != 1
|
74
|
+
end
|
75
|
+
def <(other)
|
76
|
+
(self <=> other) == -1
|
77
|
+
end
|
78
|
+
|
79
|
+
# Compares two ClusterTime instances by comparing their timestamps.
|
80
|
+
def ==(other)
|
81
|
+
if self['clusterTime'] && other['clusterTime'] &&
|
82
|
+
self['clusterTime'] == other['clusterTime']
|
83
|
+
then
|
84
|
+
true
|
85
|
+
else
|
86
|
+
false
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
class << self
|
91
|
+
# Converts a BSON::Document to a ClusterTime.
|
92
|
+
#
|
93
|
+
# +doc+ can be nil, in which case nil is returned.
|
94
|
+
def [](doc)
|
95
|
+
if doc.nil? || doc.is_a?(ClusterTime)
|
96
|
+
doc
|
97
|
+
else
|
98
|
+
ClusterTime.new(doc)
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
# This module provides common cluster time tracking behavior.
|
104
|
+
#
|
105
|
+
# @note Although attributes and methods defined in this module are part of
|
106
|
+
# the public API for the classes including this module, the fact that
|
107
|
+
# the methods are defined on this module and not directly on the
|
108
|
+
# including classes is not part of the public API.
|
109
|
+
module Consumer
|
110
|
+
|
111
|
+
# The cluster time tracked by the object including this module.
|
112
|
+
#
|
113
|
+
# @return [ nil | ClusterTime ] The cluster time.
|
114
|
+
#
|
115
|
+
# Changed in version 2.9.0: This attribute became an instance of
|
116
|
+
# ClusterTime, which is a subclass of BSON::Document.
|
117
|
+
# Previously it was an instance of BSON::Document.
|
118
|
+
#
|
119
|
+
# @since 2.5.0
|
120
|
+
attr_reader :cluster_time
|
121
|
+
|
122
|
+
# Advance the tracked cluster time document for the object including
|
123
|
+
# this module.
|
124
|
+
#
|
125
|
+
# @param [ BSON::Document ] new_cluster_time The new cluster time document.
|
126
|
+
#
|
127
|
+
# @return [ ClusterTime ] The resulting cluster time.
|
128
|
+
#
|
129
|
+
# @since 2.5.0
|
130
|
+
def advance_cluster_time(new_cluster_time)
|
131
|
+
if @cluster_time
|
132
|
+
@cluster_time = @cluster_time.advance(new_cluster_time)
|
133
|
+
else
|
134
|
+
@cluster_time = ClusterTime[new_cluster_time]
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
data/lib/mongo/collection.rb
CHANGED
@@ -53,7 +53,7 @@ module Mongo
|
|
53
53
|
# Options that can be updated on a new Collection instance via the #with method.
|
54
54
|
#
|
55
55
|
# @since 2.1.0
|
56
|
-
CHANGEABLE_OPTIONS = [ :read, :read_concern, :write ].freeze
|
56
|
+
CHANGEABLE_OPTIONS = [ :read, :read_concern, :write, :write_concern ].freeze
|
57
57
|
|
58
58
|
# Check if a collection is equal to another object. Will check the name and
|
59
59
|
# the database for equality.
|
@@ -80,12 +80,28 @@ module Mongo
|
|
80
80
|
# @param [ String, Symbol ] name The collection name.
|
81
81
|
# @param [ Hash ] options The collection options.
|
82
82
|
#
|
83
|
+
# @option options [ Hash ] :write Deprecated. Equivalent to :write_concern
|
84
|
+
# option.
|
85
|
+
# @option options [ Hash ] :write_concern The write concern options.
|
86
|
+
# Can be :w => Integer|String, :fsync => Boolean, :j => Boolean.
|
87
|
+
#
|
83
88
|
# @since 2.0.0
|
84
89
|
def initialize(database, name, options = {})
|
85
90
|
raise Error::InvalidCollectionName.new unless name
|
91
|
+
if options[:write] && options[:write_concern] && options[:write] != options[:write_concern]
|
92
|
+
raise ArgumentError, "If :write and :write_concern are both given, they must be identical: #{options.inspect}"
|
93
|
+
end
|
86
94
|
@database = database
|
87
95
|
@name = name.to_s.freeze
|
88
|
-
@options = options.
|
96
|
+
@options = options.dup
|
97
|
+
=begin WriteConcern object support
|
98
|
+
if @options[:write_concern].is_a?(WriteConcern::Base)
|
99
|
+
# Cache the instance so that we do not needlessly reconstruct it.
|
100
|
+
@write_concern = @options[:write_concern]
|
101
|
+
@options[:write_concern] = @write_concern.options
|
102
|
+
end
|
103
|
+
=end
|
104
|
+
@options.freeze
|
89
105
|
end
|
90
106
|
|
91
107
|
# Get the read concern for this collection instance.
|
@@ -133,17 +149,40 @@ module Mongo
|
|
133
149
|
#
|
134
150
|
# @since 2.0.0
|
135
151
|
def write_concern
|
136
|
-
@write_concern ||= WriteConcern.get(
|
152
|
+
@write_concern ||= WriteConcern.get(
|
153
|
+
options[:write_concern] || options[:write] || database.write_concern)
|
154
|
+
end
|
155
|
+
|
156
|
+
# Get the write concern for the collection, given the session.
|
157
|
+
#
|
158
|
+
# If the session is in a transaction and the collection
|
159
|
+
# has an unacknowledged write concern, remove the write
|
160
|
+
# concern's :w option. Otherwise, return the unmodified
|
161
|
+
# write concern.
|
162
|
+
#
|
163
|
+
# @return [ Mongo::WriteConcern ] The write concern.
|
164
|
+
#
|
165
|
+
# @api private
|
166
|
+
def write_concern_with_session(session)
|
167
|
+
wc = write_concern
|
168
|
+
if session && session.in_transaction?
|
169
|
+
if wc && !wc.acknowledged?
|
170
|
+
opts = wc.options.dup
|
171
|
+
opts.delete(:w)
|
172
|
+
return WriteConcern.get(opts)
|
173
|
+
end
|
174
|
+
end
|
175
|
+
wc
|
137
176
|
end
|
138
177
|
|
139
178
|
# Provides a new collection with either a new read preference or new write concern
|
140
179
|
# merged over the existing read preference / write concern.
|
141
180
|
#
|
142
|
-
# @example Get a collection with changed read preference.
|
143
|
-
# collection.with(:
|
181
|
+
# @example Get a collection with a changed read preference.
|
182
|
+
# collection.with(read: { mode: :primary_preferred })
|
144
183
|
#
|
145
|
-
# @example Get a collection with changed write concern.
|
146
|
-
# collection.with(:
|
184
|
+
# @example Get a collection with a changed write concern.
|
185
|
+
# collection.with(write_concern: { w: 3 })
|
147
186
|
|
148
187
|
# @param [ Hash ] new_options The new options to use.
|
149
188
|
#
|
@@ -154,7 +193,14 @@ module Mongo
|
|
154
193
|
new_options.keys.each do |k|
|
155
194
|
raise Error::UnchangeableCollectionOption.new(k) unless CHANGEABLE_OPTIONS.include?(k)
|
156
195
|
end
|
157
|
-
|
196
|
+
options = @options.dup
|
197
|
+
if options[:write] && new_options[:write_concern]
|
198
|
+
options.delete(:write)
|
199
|
+
end
|
200
|
+
if options[:write_concern] && new_options[:write]
|
201
|
+
options.delete(:write_concern)
|
202
|
+
end
|
203
|
+
Collection.new(database, name, options.update(new_options))
|
158
204
|
end
|
159
205
|
|
160
206
|
# Is the collection capped?
|
@@ -166,7 +212,7 @@ module Mongo
|
|
166
212
|
#
|
167
213
|
# @since 2.0.0
|
168
214
|
def capped?
|
169
|
-
database.
|
215
|
+
database.command(:collstats => name).documents[0][CAPPED]
|
170
216
|
end
|
171
217
|
|
172
218
|
# Force the collection to be created in the database.
|
@@ -182,13 +228,22 @@ module Mongo
|
|
182
228
|
#
|
183
229
|
# @since 2.0.0
|
184
230
|
def create(opts = {})
|
231
|
+
# Passing read options to create command causes it to break.
|
232
|
+
# Filter the read options out.
|
233
|
+
# TODO put the list of read options in a class-level constant when
|
234
|
+
# we figure out what the full set of them is.
|
235
|
+
options = Hash[self.options.reject do |key, value|
|
236
|
+
%w(read read_preference).include?(key.to_s)
|
237
|
+
end]
|
185
238
|
operation = { :create => name }.merge(options)
|
186
239
|
operation.delete(:write)
|
187
|
-
|
188
|
-
if (options[:collation] || options[Operation::COLLATION]) && !server.features.collation_enabled?
|
189
|
-
raise Error::UnsupportedCollation.new
|
190
|
-
end
|
240
|
+
operation.delete(:write_concern)
|
191
241
|
client.send(:with_session, opts) do |session|
|
242
|
+
server = next_primary(nil, session)
|
243
|
+
if (options[:collation] || options[Operation::COLLATION]) && !server.features.collation_enabled?
|
244
|
+
raise Error::UnsupportedCollation
|
245
|
+
end
|
246
|
+
|
192
247
|
Operation::Create.new({
|
193
248
|
selector: operation,
|
194
249
|
db_name: database.name,
|
@@ -220,7 +275,7 @@ module Mongo
|
|
220
275
|
db_name: database.name,
|
221
276
|
write_concern: write_concern,
|
222
277
|
session: session
|
223
|
-
}).execute(next_primary)
|
278
|
+
}).execute(next_primary(nil, session))
|
224
279
|
end
|
225
280
|
rescue Error::OperationFailure => ex
|
226
281
|
raise ex unless ex.message =~ /ns not found/
|
@@ -277,18 +332,21 @@ module Mongo
|
|
277
332
|
# @param [ Array<Hash> ] pipeline The aggregation pipeline.
|
278
333
|
# @param [ Hash ] options The aggregation options.
|
279
334
|
#
|
280
|
-
# @option options [ true, false ] :allow_disk_use Set to true if disk
|
281
|
-
# the aggregation.
|
282
|
-
# @option options [ Integer ] :batch_size The number of documents to return
|
283
|
-
#
|
284
|
-
# aggregation to run.
|
285
|
-
# @option options [ true, false ] :use_cursor Indicates whether the command will request that the server
|
286
|
-
# provide results using a cursor. Note that as of server version 3.6, aggregations always provide results
|
287
|
-
# using a cursor and this option is therefore not valid.
|
335
|
+
# @option options [ true, false ] :allow_disk_use Set to true if disk
|
336
|
+
# usage is allowed during the aggregation.
|
337
|
+
# @option options [ Integer ] :batch_size The number of documents to return
|
338
|
+
# per batch.
|
288
339
|
# @option options [ true, false ] :bypass_document_validation Whether or
|
289
340
|
# not to skip document level validation.
|
290
341
|
# @option options [ Hash ] :collation The collation to use.
|
291
342
|
# @option options [ String ] :comment Associate a comment with the aggregation.
|
343
|
+
# @option options [ String ] :hint The index to use for the aggregation.
|
344
|
+
# @option options [ Integer ] :max_time_ms The maximum amount of time in
|
345
|
+
# milliseconds to allow the aggregation to run.
|
346
|
+
# @option options [ true, false ] :use_cursor Indicates whether the command
|
347
|
+
# will request that the server provide results using a cursor. Note that
|
348
|
+
# as of server version 3.6, aggregations always provide results using a
|
349
|
+
# cursor and this option is therefore not valid.
|
292
350
|
# @option options [ Session ] :session The session to use.
|
293
351
|
#
|
294
352
|
# @return [ Aggregation ] The aggregation object.
|
@@ -475,6 +533,7 @@ module Mongo
|
|
475
533
|
# @since 2.0.0
|
476
534
|
def insert_one(document, opts = {})
|
477
535
|
client.send(:with_session, opts) do |session|
|
536
|
+
write_concern = write_concern_with_session(session)
|
478
537
|
write_with_retry(session, write_concern) do |server, txn_num|
|
479
538
|
Operation::Insert.new(
|
480
539
|
:documents => [ document ],
|
@@ -620,7 +679,7 @@ module Mongo
|
|
620
679
|
# collection.update_many({ name: 'test'}, '$set' => { name: 'test1' })
|
621
680
|
#
|
622
681
|
# @param [ Hash ] filter The filter to use.
|
623
|
-
# @param [ Hash ] update The update
|
682
|
+
# @param [ Hash | Array<Hash> ] update The update document or pipeline.
|
624
683
|
# @param [ Hash ] options The options.
|
625
684
|
#
|
626
685
|
# @option options [ true, false ] :upsert Whether to upsert if the
|
@@ -645,7 +704,7 @@ module Mongo
|
|
645
704
|
# collection.update_one({ name: 'test'}, '$set' => { name: 'test1'})
|
646
705
|
#
|
647
706
|
# @param [ Hash ] filter The filter to use.
|
648
|
-
# @param [ Hash ] update The update
|
707
|
+
# @param [ Hash | Array<Hash> ] update The update document or pipeline.
|
649
708
|
# @param [ Hash ] options The options.
|
650
709
|
#
|
651
710
|
# @option options [ true, false ] :upsert Whether to upsert if the
|
@@ -700,7 +759,7 @@ module Mongo
|
|
700
759
|
# collection.find_one_and_update({ name: 'test' }, { "$set" => { name: 'test1' }}, :return_document => :after)
|
701
760
|
#
|
702
761
|
# @param [ Hash ] filter The filter to use.
|
703
|
-
# @param [
|
762
|
+
# @param [ Hash | Array<Hash> ] update The update document or pipeline.
|
704
763
|
# @param [ Hash ] options The options.
|
705
764
|
#
|
706
765
|
# @option options [ Integer ] :max_time_ms The maximum amount of time to allow the command
|