mongo 2.16.3 → 2.17.2
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/README.md +1 -1
- data/lib/mongo/auth/aws/request.rb +0 -1
- data/lib/mongo/client.rb +4 -0
- data/lib/mongo/cluster/reapers/cursor_reaper.rb +26 -14
- data/lib/mongo/collection/view/aggregation.rb +62 -17
- data/lib/mongo/collection/view/builder/aggregation.rb +11 -13
- data/lib/mongo/collection/view/builder/map_reduce.rb +1 -1
- data/lib/mongo/collection/view/change_stream.rb +7 -3
- data/lib/mongo/collection/view/iterable.rb +2 -3
- data/lib/mongo/collection/view/map_reduce.rb +2 -0
- data/lib/mongo/collection/view/readable.rb +24 -1
- data/lib/mongo/collection/view/writable.rb +23 -0
- data/lib/mongo/collection.rb +21 -1
- data/lib/mongo/cursor/kill_spec.rb +19 -2
- data/lib/mongo/cursor.rb +5 -5
- data/lib/mongo/database/view.rb +4 -2
- data/lib/mongo/database.rb +6 -6
- data/lib/mongo/error/snapshot_session_invalid_server_version.rb +31 -0
- data/lib/mongo/error/snapshot_session_transaction_prohibited.rb +30 -0
- data/lib/mongo/error.rb +2 -0
- data/lib/mongo/operation/delete/op_msg.rb +2 -1
- data/lib/mongo/operation/find/builder/command.rb +1 -0
- data/lib/mongo/operation/result.rb +6 -0
- data/lib/mongo/operation/shared/executable.rb +4 -0
- data/lib/mongo/operation/shared/sessions_supported.rb +18 -2
- data/lib/mongo/operation/update/op_msg.rb +2 -1
- data/lib/mongo/server/description/features.rb +3 -1
- data/lib/mongo/server_selector/base.rb +26 -4
- data/lib/mongo/session.rb +19 -0
- data/lib/mongo/socket/ocsp_cache.rb +2 -3
- data/lib/mongo/socket.rb +1 -5
- data/lib/mongo/utils.rb +0 -6
- data/lib/mongo/version.rb +1 -1
- data/mongo.gemspec +1 -1
- data/spec/integration/read_preference_spec.rb +16 -12
- data/spec/mongo/cluster/cursor_reaper_spec.rb +22 -15
- data/spec/mongo/collection/view/aggregation_spec.rb +71 -95
- data/spec/mongo/collection/view/change_stream_spec.rb +1 -1
- data/spec/mongo/collection/view/map_reduce_spec.rb +14 -1
- data/spec/mongo/cursor_spec.rb +3 -2
- data/spec/mongo/operation/read_preference_op_msg_spec.rb +24 -1
- data/spec/mongo/server_selector_spec.rb +136 -15
- data/spec/mongo/socket/ssl_spec.rb +26 -58
- data/spec/mongo/utils_spec.rb +0 -14
- data/spec/runners/crud/verifier.rb +1 -2
- data/spec/runners/unified/assertions.rb +3 -1
- data/spec/runners/unified/crud_operations.rb +77 -23
- data/spec/runners/unified/ddl_operations.rb +29 -1
- data/spec/runners/unified/entity_map.rb +3 -3
- data/spec/runners/unified/support_operations.rb +6 -1
- data/spec/runners/unified/test.rb +15 -3
- data/spec/spec_tests/data/crud_unified/aggregate-let.yml +138 -0
- data/spec/spec_tests/data/crud_unified/aggregate-write-readPreference.yml +155 -0
- data/spec/spec_tests/data/crud_unified/db-aggregate-write-readPreference.yml +151 -0
- data/spec/spec_tests/data/crud_unified/deleteMany-let.yml +91 -0
- data/spec/spec_tests/data/crud_unified/deleteOne-let.yml +89 -0
- data/spec/spec_tests/data/crud_unified/find-let.yml +71 -0
- data/spec/spec_tests/data/crud_unified/findOneAndDelete-let.yml +88 -0
- data/spec/spec_tests/data/crud_unified/findOneAndReplace-let.yml +94 -0
- data/spec/spec_tests/data/crud_unified/findOneAndUpdate-let.yml +96 -0
- data/spec/spec_tests/data/crud_unified/updateMany-let.yml +103 -0
- data/spec/spec_tests/data/crud_unified/updateOne-let.yml +98 -0
- data/spec/spec_tests/data/max_staleness/ReplicaSetNoPrimary/DefaultNoMaxStaleness.yml +2 -2
- data/spec/spec_tests/data/max_staleness/ReplicaSetNoPrimary/LastUpdateTime.yml +3 -3
- data/spec/spec_tests/data/max_staleness/ReplicaSetNoPrimary/Nearest.yml +3 -3
- data/spec/spec_tests/data/max_staleness/ReplicaSetNoPrimary/Nearest2.yml +3 -3
- data/spec/spec_tests/data/max_staleness/ReplicaSetNoPrimary/PrimaryPreferred.yml +2 -2
- data/spec/spec_tests/data/max_staleness/ReplicaSetNoPrimary/PrimaryPreferred_tags.yml +2 -2
- data/spec/spec_tests/data/max_staleness/ReplicaSetNoPrimary/Secondary.yml +4 -4
- data/spec/spec_tests/data/max_staleness/ReplicaSetNoPrimary/SecondaryPreferred.yml +2 -2
- data/spec/spec_tests/data/max_staleness/ReplicaSetNoPrimary/SecondaryPreferred_tags.yml +4 -4
- data/spec/spec_tests/data/max_staleness/ReplicaSetNoPrimary/ZeroMaxStaleness.yml +2 -2
- data/spec/spec_tests/data/max_staleness/ReplicaSetWithPrimary/DefaultNoMaxStaleness.yml +2 -2
- data/spec/spec_tests/data/max_staleness/ReplicaSetWithPrimary/LastUpdateTime.yml +3 -3
- data/spec/spec_tests/data/max_staleness/ReplicaSetWithPrimary/LongHeartbeat.yml +2 -2
- data/spec/spec_tests/data/max_staleness/ReplicaSetWithPrimary/LongHeartbeat2.yml +2 -2
- data/spec/spec_tests/data/max_staleness/ReplicaSetWithPrimary/MaxStalenessTooSmall.yml +2 -2
- data/spec/spec_tests/data/max_staleness/ReplicaSetWithPrimary/MaxStalenessWithModePrimary.yml +2 -2
- data/spec/spec_tests/data/max_staleness/ReplicaSetWithPrimary/Nearest.yml +3 -3
- data/spec/spec_tests/data/max_staleness/ReplicaSetWithPrimary/Nearest2.yml +3 -3
- data/spec/spec_tests/data/max_staleness/ReplicaSetWithPrimary/Nearest_tags.yml +2 -2
- data/spec/spec_tests/data/max_staleness/ReplicaSetWithPrimary/PrimaryPreferred.yml +2 -2
- data/spec/spec_tests/data/max_staleness/ReplicaSetWithPrimary/SecondaryPreferred.yml +2 -2
- data/spec/spec_tests/data/max_staleness/ReplicaSetWithPrimary/SecondaryPreferred_tags.yml +5 -5
- data/spec/spec_tests/data/max_staleness/ReplicaSetWithPrimary/SecondaryPreferred_tags2.yml +3 -3
- data/spec/spec_tests/data/max_staleness/ReplicaSetWithPrimary/Secondary_tags.yml +5 -5
- data/spec/spec_tests/data/max_staleness/ReplicaSetWithPrimary/Secondary_tags2.yml +3 -3
- data/spec/spec_tests/data/max_staleness/ReplicaSetWithPrimary/ZeroMaxStaleness.yml +2 -2
- data/spec/spec_tests/data/max_staleness/Sharded/SmallMaxStaleness.yml +2 -2
- data/spec/spec_tests/data/max_staleness/Single/SmallMaxStaleness.yml +1 -1
- data/spec/spec_tests/data/max_staleness/Unknown/SmallMaxStaleness.yml +1 -1
- data/spec/spec_tests/data/sessions_unified/snapshot-sessions-not-supported-client-error.yml +69 -0
- data/spec/spec_tests/data/sessions_unified/snapshot-sessions-not-supported-server-error.yml +102 -0
- data/spec/spec_tests/data/sessions_unified/snapshot-sessions-unsupported-ops.yml +258 -0
- data/spec/spec_tests/data/sessions_unified/snapshot-sessions.yml +482 -0
- data/spec/spec_tests/sessions_unified_spec.rb +13 -0
- data.tar.gz.sig +0 -0
- metadata +36 -2
- metadata.gz.sig +0 -0
data/lib/mongo/cursor.rb
CHANGED
@@ -84,9 +84,8 @@ module Mongo
|
|
84
84
|
@session = @options[:session]
|
85
85
|
unless closed?
|
86
86
|
register
|
87
|
-
ObjectSpace.define_finalizer(self, self.class.finalize(kill_spec,
|
87
|
+
ObjectSpace.define_finalizer(self, self.class.finalize(kill_spec(server),
|
88
88
|
cluster,
|
89
|
-
server,
|
90
89
|
@session))
|
91
90
|
end
|
92
91
|
end
|
@@ -107,12 +106,12 @@ module Mongo
|
|
107
106
|
# @return [ Proc ] The Finalizer.
|
108
107
|
#
|
109
108
|
# @api private
|
110
|
-
def self.finalize(kill_spec, cluster,
|
109
|
+
def self.finalize(kill_spec, cluster, session)
|
111
110
|
unless KillSpec === kill_spec
|
112
111
|
raise ArgumentError, "First argument must be a KillSpec: #{kill_spec.inspect}"
|
113
112
|
end
|
114
113
|
proc do
|
115
|
-
cluster.schedule_kill_cursor(kill_spec
|
114
|
+
cluster.schedule_kill_cursor(kill_spec)
|
116
115
|
session.end_session if session && session.implicit?
|
117
116
|
end
|
118
117
|
end
|
@@ -367,12 +366,13 @@ module Mongo
|
|
367
366
|
end
|
368
367
|
|
369
368
|
# @api private
|
370
|
-
def kill_spec
|
369
|
+
def kill_spec(server)
|
371
370
|
KillSpec.new(
|
372
371
|
cursor_id: id,
|
373
372
|
coll_name: collection_name,
|
374
373
|
db_name: database.name,
|
375
374
|
service_id: initial_result.connection_description.service_id,
|
375
|
+
server_address: server.address,
|
376
376
|
)
|
377
377
|
end
|
378
378
|
|
data/lib/mongo/database/view.rb
CHANGED
@@ -28,7 +28,7 @@ module Mongo
|
|
28
28
|
|
29
29
|
def_delegators :@database, :cluster, :read_preference, :client
|
30
30
|
# @api private
|
31
|
-
def_delegators :@database, :server_selector, :read_concern
|
31
|
+
def_delegators :@database, :server_selector, :read_concern, :write_concern
|
32
32
|
def_delegators :cluster, :next_primary
|
33
33
|
|
34
34
|
# @return [ Integer ] batch_size The size of the batch of results
|
@@ -57,6 +57,7 @@ module Mongo
|
|
57
57
|
#
|
58
58
|
# See https://docs.mongodb.com/manual/reference/command/listCollections/
|
59
59
|
# for more information and usage.
|
60
|
+
# @option options [ Session ] :session The session to use.
|
60
61
|
#
|
61
62
|
# @return [ Array<String> ] The names of all non-system collections.
|
62
63
|
#
|
@@ -100,12 +101,13 @@ module Mongo
|
|
100
101
|
#
|
101
102
|
# See https://docs.mongodb.com/manual/reference/command/listCollections/
|
102
103
|
# for more information and usage.
|
104
|
+
# @option options [ Session ] :session The session to use.
|
103
105
|
#
|
104
106
|
# @return [ Array<Hash> ] Info for each collection in the database.
|
105
107
|
#
|
106
108
|
# @since 2.0.5
|
107
109
|
def list_collections(options = {})
|
108
|
-
session = client.send(:get_session)
|
110
|
+
session = client.send(:get_session, options)
|
109
111
|
collections_info(session, ServerSelector.primary, options)
|
110
112
|
end
|
111
113
|
|
data/lib/mongo/database.rb
CHANGED
@@ -253,12 +253,12 @@ module Mongo
|
|
253
253
|
|
254
254
|
client.send(:with_session, opts) do |session|
|
255
255
|
read_with_retry(session, preference) do |server|
|
256
|
-
Operation::Command.new(
|
257
|
-
:
|
258
|
-
:
|
259
|
-
:
|
260
|
-
:
|
261
|
-
|
256
|
+
Operation::Command.new(
|
257
|
+
selector: operation.dup,
|
258
|
+
db_name: name,
|
259
|
+
read: preference,
|
260
|
+
session: session,
|
261
|
+
).execute(server, context: Operation::Context.new(client: client, session: session))
|
262
262
|
end
|
263
263
|
end
|
264
264
|
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
# encoding: utf-8
|
3
|
+
|
4
|
+
# Copyright (C) 2021 MongoDB Inc.
|
5
|
+
#
|
6
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
7
|
+
# you may not use this file except in compliance with the License.
|
8
|
+
# You may obtain a copy of the License at
|
9
|
+
#
|
10
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
11
|
+
#
|
12
|
+
# Unless required by applicable law or agreed to in writing, software
|
13
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
14
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
15
|
+
# See the License for the specific language governing permissions and
|
16
|
+
# limitations under the License.
|
17
|
+
|
18
|
+
module Mongo
|
19
|
+
class Error
|
20
|
+
|
21
|
+
# Exception raised if an operation using a snapshot session is
|
22
|
+
# directed to a pre-5.0 server.
|
23
|
+
class SnapshotSessionInvalidServerVersion < Error
|
24
|
+
|
25
|
+
# Instantiate the new exception.
|
26
|
+
def initialize
|
27
|
+
super("Snapshot reads require MongoDB 5.0 or later")
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
# encoding: utf-8
|
3
|
+
|
4
|
+
# Copyright (C) 2021 MongoDB Inc.
|
5
|
+
#
|
6
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
7
|
+
# you may not use this file except in compliance with the License.
|
8
|
+
# You may obtain a copy of the License at
|
9
|
+
#
|
10
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
11
|
+
#
|
12
|
+
# Unless required by applicable law or agreed to in writing, software
|
13
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
14
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
15
|
+
# See the License for the specific language governing permissions and
|
16
|
+
# limitations under the License.
|
17
|
+
|
18
|
+
module Mongo
|
19
|
+
class Error
|
20
|
+
|
21
|
+
# Exception raised if a transaction is attempted on a snapshot session.
|
22
|
+
class SnapshotSessionTransactionProhibited < Error
|
23
|
+
|
24
|
+
# Instantiate the new exception.
|
25
|
+
def initialize
|
26
|
+
super("Transactions are not supported in snapshot sessions")
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
data/lib/mongo/error.rb
CHANGED
@@ -223,6 +223,8 @@ require 'mongo/error/no_server_available'
|
|
223
223
|
require 'mongo/error/no_srv_records'
|
224
224
|
require 'mongo/error/session_ended'
|
225
225
|
require 'mongo/error/sessions_not_supported'
|
226
|
+
require 'mongo/error/snapshot_session_invalid_server_version'
|
227
|
+
require 'mongo/error/snapshot_session_transaction_prohibited'
|
226
228
|
require 'mongo/error/operation_failure'
|
227
229
|
require 'mongo/error/pool_closed_error'
|
228
230
|
require 'mongo/error/raise_original_error'
|
@@ -37,7 +37,8 @@ module Mongo
|
|
37
37
|
{ delete: coll_name,
|
38
38
|
Protocol::Msg::DATABASE_IDENTIFIER => db_name,
|
39
39
|
ordered: ordered?,
|
40
|
-
|
40
|
+
let: spec[:let],
|
41
|
+
}.compact.tap do |selector|
|
41
42
|
if hint = spec[:hint]
|
42
43
|
validate_hint_on_update(connection, selector)
|
43
44
|
selector[:hint] = hint
|
@@ -429,6 +429,12 @@ module Mongo
|
|
429
429
|
!!(first_document && first_document['writeConcernError'])
|
430
430
|
end
|
431
431
|
|
432
|
+
def snapshot_timestamp
|
433
|
+
if doc = reply.documents.first
|
434
|
+
doc['cursor']&.[]('atClusterTime') || doc['atClusterTime']
|
435
|
+
end
|
436
|
+
end
|
437
|
+
|
432
438
|
private
|
433
439
|
|
434
440
|
def aggregate_returned_count
|
@@ -199,8 +199,13 @@ module Mongo
|
|
199
199
|
read_doc
|
200
200
|
else
|
201
201
|
# In replica sets, read preference is passed to the server if one
|
202
|
-
# is specified by the application,
|
203
|
-
read&.to_doc
|
202
|
+
# is specified by the application, except for primary read preferences.
|
203
|
+
read_doc = BSON::Document.new(read&.to_doc || {})
|
204
|
+
if [nil, 'primary'].include?(read_doc['mode'])
|
205
|
+
nil
|
206
|
+
else
|
207
|
+
read_doc
|
208
|
+
end
|
204
209
|
end
|
205
210
|
|
206
211
|
if read_doc
|
@@ -224,6 +229,17 @@ module Mongo
|
|
224
229
|
then
|
225
230
|
sel[:recoveryToken] = session.recovery_token
|
226
231
|
end
|
232
|
+
|
233
|
+
if session.snapshot?
|
234
|
+
unless connection.description.server_version_gte?('5.0')
|
235
|
+
raise Error::SnapshotSessionInvalidServerVersion
|
236
|
+
end
|
237
|
+
|
238
|
+
sel[:readConcern] = {level: 'snapshot'}
|
239
|
+
if session.snapshot_timestamp
|
240
|
+
sel[:readConcern][:atClusterTime] = session.snapshot_timestamp
|
241
|
+
end
|
242
|
+
end
|
227
243
|
end
|
228
244
|
|
229
245
|
def build_message(connection, context)
|
@@ -35,9 +35,11 @@ module Mongo
|
|
35
35
|
# - 8 => 4.2
|
36
36
|
# - 9 => 4.4
|
37
37
|
# - 13 => 5.0
|
38
|
+
# - 14 => 5.1
|
38
39
|
#
|
39
40
|
# @since 2.0.0
|
40
41
|
MAPPINGS = {
|
42
|
+
merge_out_on_secondary: 13,
|
41
43
|
retryable_write_error_label: 9,
|
42
44
|
commit_quorum: 9,
|
43
45
|
# Server versions older than 4.2 do not reliably validate options
|
@@ -78,7 +80,7 @@ module Mongo
|
|
78
80
|
# The wire protocol versions that this version of the driver supports.
|
79
81
|
#
|
80
82
|
# @since 2.0.0
|
81
|
-
DRIVER_WIRE_VERSIONS = (
|
83
|
+
DRIVER_WIRE_VERSIONS = (6..14).freeze
|
82
84
|
|
83
85
|
# Create the methods for each mapping to tell if they are supported.
|
84
86
|
#
|
@@ -162,6 +162,8 @@ module Mongo
|
|
162
162
|
# Deprecated and ignored.
|
163
163
|
# @param [ Session | nil ] session Optional session to take into account
|
164
164
|
# for mongos pinning. Added in version 2.10.0.
|
165
|
+
# @param [ true | false ] write_aggregation Whether we need a server that
|
166
|
+
# supports writing aggregations (e.g. with $merge/$out) on secondaries.
|
165
167
|
#
|
166
168
|
# @return [ Mongo::Server ] A server matching the server preference.
|
167
169
|
#
|
@@ -172,7 +174,7 @@ module Mongo
|
|
172
174
|
# lint mode is enabled.
|
173
175
|
#
|
174
176
|
# @since 2.0.0
|
175
|
-
def select_server(cluster, ping = nil, session = nil)
|
177
|
+
def select_server(cluster, ping = nil, session = nil, write_aggregation: false)
|
176
178
|
if cluster.topology.is_a?(Cluster::Topology::LoadBalanced)
|
177
179
|
return cluster.servers.first
|
178
180
|
end
|
@@ -243,7 +245,7 @@ module Mongo
|
|
243
245
|
=end
|
244
246
|
|
245
247
|
loop do
|
246
|
-
server = try_select_server(cluster)
|
248
|
+
server = try_select_server(cluster, write_aggregation: write_aggregation)
|
247
249
|
|
248
250
|
if server
|
249
251
|
unless cluster.topology.compatible?
|
@@ -294,11 +296,31 @@ module Mongo
|
|
294
296
|
# Tries to find a suitable server, returns the server if one is available
|
295
297
|
# or nil if there isn't a suitable server.
|
296
298
|
#
|
299
|
+
# @param [ Mongo::Cluster ] cluster The cluster from which to select
|
300
|
+
# an eligible server.
|
301
|
+
# @param [ true | false ] write_aggregation Whether we need a server that
|
302
|
+
# supports writing aggregations (e.g. with $merge/$out) on secondaries.
|
303
|
+
#
|
297
304
|
# @return [ Server | nil ] A suitable server, if one exists.
|
298
305
|
#
|
299
306
|
# @api private
|
300
|
-
def try_select_server(cluster)
|
301
|
-
servers =
|
307
|
+
def try_select_server(cluster, write_aggregation: false)
|
308
|
+
servers = if write_aggregation && cluster.replica_set?
|
309
|
+
# 1. Check if ALL servers in cluster support secondary writes.
|
310
|
+
is_write_supported = cluster.servers.reduce(true) do |res, server|
|
311
|
+
res && server.features.merge_out_on_secondary_enabled?
|
312
|
+
end
|
313
|
+
|
314
|
+
if is_write_supported
|
315
|
+
# 2. If all servers support secondary writes, we respect read preference.
|
316
|
+
suitable_servers(cluster)
|
317
|
+
else
|
318
|
+
# 3. Otherwise we fallback to primary for replica set.
|
319
|
+
[cluster.servers.detect(&:primary?)]
|
320
|
+
end
|
321
|
+
else
|
322
|
+
suitable_servers(cluster)
|
323
|
+
end
|
302
324
|
|
303
325
|
# This list of servers may be ordered in a specific way
|
304
326
|
# by the selector (e.g. for secondary preferred, the first
|
data/lib/mongo/session.rb
CHANGED
@@ -56,10 +56,16 @@ module Mongo
|
|
56
56
|
# - *:mode* -- the read preference as a string or symbol; valid values are
|
57
57
|
# *:primary*, *:primary_preferred*, *:secondary*, *:secondary_preferred*
|
58
58
|
# and *:nearest*.
|
59
|
+
# @option options [ true | false ] :snapshot Set up the session for
|
60
|
+
# snapshot reads.
|
59
61
|
#
|
60
62
|
# @since 2.5.0
|
61
63
|
# @api private
|
62
64
|
def initialize(server_session, client, options = {})
|
65
|
+
if options[:causal_consistency] && options[:snapshot]
|
66
|
+
raise ArgumentError, ':causal_consistency and :snapshot options cannot be both set on a session'
|
67
|
+
end
|
68
|
+
|
63
69
|
@server_session = server_session
|
64
70
|
options = options.dup
|
65
71
|
|
@@ -83,6 +89,12 @@ module Mongo
|
|
83
89
|
@client.cluster
|
84
90
|
end
|
85
91
|
|
92
|
+
# @return [ true | false ] Whether the session is configured for snapshot
|
93
|
+
# reads.
|
94
|
+
def snapshot?
|
95
|
+
!!options[:snapshot]
|
96
|
+
end
|
97
|
+
|
86
98
|
# @return [ BSON::Timestamp ] The latest seen operation time for this session.
|
87
99
|
#
|
88
100
|
# @since 2.5.0
|
@@ -506,6 +518,10 @@ module Mongo
|
|
506
518
|
=end
|
507
519
|
end
|
508
520
|
|
521
|
+
if snapshot?
|
522
|
+
raise Mongo::Error::SnapshotSessionTransactionProhibited
|
523
|
+
end
|
524
|
+
|
509
525
|
check_if_ended!
|
510
526
|
|
511
527
|
if within_states?(STARTING_TRANSACTION_STATE, TRANSACTION_IN_PROGRESS_STATE)
|
@@ -1024,6 +1040,9 @@ module Mongo
|
|
1024
1040
|
@server_session.txn_num
|
1025
1041
|
end
|
1026
1042
|
|
1043
|
+
# @api private
|
1044
|
+
attr_accessor :snapshot_timestamp
|
1045
|
+
|
1027
1046
|
private
|
1028
1047
|
|
1029
1048
|
# Get the read concern the session will use when starting a transaction.
|
@@ -21,8 +21,7 @@ module Mongo
|
|
21
21
|
# This module caches OCSP responses for their indicated validity time.
|
22
22
|
#
|
23
23
|
# The key is the CertificateId used for the OCSP request.
|
24
|
-
# The value is the SingleResponse
|
25
|
-
# emulation of it on Ruby 2.3.
|
24
|
+
# The value is the SingleResponse.
|
26
25
|
#
|
27
26
|
# @api private
|
28
27
|
module OcspCache
|
@@ -40,7 +39,7 @@ module Mongo
|
|
40
39
|
# expire by the time caller uses them. The caller should not perform
|
41
40
|
# update time checks on the returned response.
|
42
41
|
#
|
43
|
-
# @return [ OpenSSL::OCSP::SingleResponse
|
42
|
+
# @return [ OpenSSL::OCSP::SingleResponse ] The previously
|
44
43
|
# retrieved response.
|
45
44
|
module_function def get(cert_id)
|
46
45
|
resp = responses.detect do |resp|
|
data/lib/mongo/socket.rb
CHANGED
@@ -362,11 +362,7 @@ module Mongo
|
|
362
362
|
end
|
363
363
|
|
364
364
|
def allocate_string(capacity)
|
365
|
-
|
366
|
-
String.new('', :capacity => capacity, :encoding => 'BINARY')
|
367
|
-
else
|
368
|
-
('x'*capacity).force_encoding('BINARY')
|
369
|
-
end
|
365
|
+
String.new('', :capacity => capacity, :encoding => 'BINARY')
|
370
366
|
end
|
371
367
|
|
372
368
|
def read_buffer_size
|
data/lib/mongo/utils.rb
CHANGED
@@ -101,11 +101,5 @@ module Mongo
|
|
101
101
|
module_function def monotonic_time
|
102
102
|
Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
103
103
|
end
|
104
|
-
|
105
|
-
# Hash#compact implementation for Ruby 2.3/2.4
|
106
|
-
# Implementation based on activesupport 5.2.3
|
107
|
-
module_function def slice_hash(hash, *keys)
|
108
|
-
keys.each_with_object({}) { |k, res| res[k] = hash[k] if hash.key?(k) }
|
109
|
-
end
|
110
104
|
end
|
111
105
|
end
|
data/lib/mongo/version.rb
CHANGED
data/mongo.gemspec
CHANGED
@@ -45,16 +45,6 @@ describe 'Read preference' do
|
|
45
45
|
{}
|
46
46
|
end
|
47
47
|
|
48
|
-
shared_examples_for 'sends expected read preference when reading' do
|
49
|
-
it 'sends expected read preference when reading' do
|
50
|
-
read_operation
|
51
|
-
|
52
|
-
event = subscriber.single_command_started_event('find')
|
53
|
-
actual_preference = event.command['$readPreference']
|
54
|
-
expect(actual_preference).to eq(expected_read_preference)
|
55
|
-
end
|
56
|
-
end
|
57
|
-
|
58
48
|
shared_examples_for 'does not send read preference when reading' do
|
59
49
|
it 'does not send read preference when reading' do
|
60
50
|
read_operation
|
@@ -95,7 +85,17 @@ describe 'Read preference' do
|
|
95
85
|
context 'server supporting OP_MSG' do
|
96
86
|
min_server_fcv '3.6'
|
97
87
|
|
98
|
-
|
88
|
+
it 'sends expected read preference when reading' do
|
89
|
+
read_operation
|
90
|
+
|
91
|
+
event = subscriber.single_command_started_event('find')
|
92
|
+
actual_preference = event.command['$readPreference']
|
93
|
+
if expected_read_preference&.[]("mode") == "primary"
|
94
|
+
expect(actual_preference).to be_nil
|
95
|
+
else
|
96
|
+
expect(actual_preference).to eq(expected_read_preference)
|
97
|
+
end
|
98
|
+
end
|
99
99
|
end
|
100
100
|
end
|
101
101
|
|
@@ -307,7 +307,11 @@ describe 'Read preference' do
|
|
307
307
|
|
308
308
|
event = subscriber.single_command_started_event('find')
|
309
309
|
actual_preference = event.command['$readPreference']
|
310
|
-
|
310
|
+
if expected_read_preference&.[]("mode") == "primary"
|
311
|
+
expect(actual_preference).to be_nil
|
312
|
+
else
|
313
|
+
expect(actual_preference).to eq(expected_read_preference)
|
314
|
+
end
|
311
315
|
end
|
312
316
|
end
|
313
317
|
end
|
@@ -41,12 +41,12 @@ describe Mongo::Cluster::CursorReaper do
|
|
41
41
|
let(:cursor_id) { 1 }
|
42
42
|
let(:cursor_kill_spec_1) do
|
43
43
|
Mongo::Cursor::KillSpec.new(
|
44
|
-
cursor_id: cursor_id, coll_name: 'c', db_name: 'd', service_id: nil,
|
44
|
+
cursor_id: cursor_id, coll_name: 'c', db_name: 'd', service_id: nil, server_address: address
|
45
45
|
)
|
46
46
|
end
|
47
47
|
let(:cursor_kill_spec_2) do
|
48
48
|
Mongo::Cursor::KillSpec.new(
|
49
|
-
cursor_id: cursor_id, coll_name: 'c', db_name: 'q', service_id: nil,
|
49
|
+
cursor_id: cursor_id, coll_name: 'c', db_name: 'q', service_id: nil, server_address: address
|
50
50
|
)
|
51
51
|
end
|
52
52
|
let(:to_kill) { reaper.instance_variable_get(:@to_kill)}
|
@@ -60,36 +60,40 @@ describe Mongo::Cluster::CursorReaper do
|
|
60
60
|
context 'when there is not a list already for the server' do
|
61
61
|
|
62
62
|
before do
|
63
|
-
reaper.schedule_kill_cursor(cursor_kill_spec_1
|
63
|
+
reaper.schedule_kill_cursor(cursor_kill_spec_1)
|
64
|
+
reaper.read_scheduled_kill_specs
|
64
65
|
end
|
65
66
|
|
66
67
|
it 'initializes the list of op specs to a set' do
|
67
|
-
expect(to_kill.keys).to eq([ address
|
68
|
-
expect(to_kill[address
|
68
|
+
expect(to_kill.keys).to eq([ address ])
|
69
|
+
expect(to_kill[address]).to contain_exactly(cursor_kill_spec_1)
|
69
70
|
end
|
70
71
|
end
|
71
72
|
|
72
73
|
context 'when there is a list of ops already for the server' do
|
73
74
|
|
74
75
|
before do
|
75
|
-
reaper.schedule_kill_cursor(cursor_kill_spec_1
|
76
|
-
reaper.
|
76
|
+
reaper.schedule_kill_cursor(cursor_kill_spec_1)
|
77
|
+
reaper.read_scheduled_kill_specs
|
78
|
+
reaper.schedule_kill_cursor(cursor_kill_spec_2)
|
79
|
+
reaper.read_scheduled_kill_specs
|
77
80
|
end
|
78
81
|
|
79
82
|
it 'adds the op to the server list' do
|
80
|
-
expect(to_kill.keys).to eq([ address
|
81
|
-
expect(to_kill[address
|
83
|
+
expect(to_kill.keys).to eq([ address ])
|
84
|
+
expect(to_kill[address]).to contain_exactly(cursor_kill_spec_1, cursor_kill_spec_2)
|
82
85
|
end
|
83
86
|
|
84
87
|
context 'when the same op is added more than once' do
|
85
88
|
|
86
89
|
before do
|
87
|
-
reaper.schedule_kill_cursor(cursor_kill_spec_2
|
90
|
+
reaper.schedule_kill_cursor(cursor_kill_spec_2)
|
91
|
+
reaper.read_scheduled_kill_specs
|
88
92
|
end
|
89
93
|
|
90
94
|
it 'does not allow duplicates ops for a server' do
|
91
|
-
expect(to_kill.keys).to eq([ address
|
92
|
-
expect(to_kill[address
|
95
|
+
expect(to_kill.keys).to eq([ address ])
|
96
|
+
expect(to_kill[address]).to contain_exactly(cursor_kill_spec_1, cursor_kill_spec_2)
|
93
97
|
end
|
94
98
|
end
|
95
99
|
end
|
@@ -98,7 +102,7 @@ describe Mongo::Cluster::CursorReaper do
|
|
98
102
|
context 'when the cursor is not on the list of active cursors' do
|
99
103
|
|
100
104
|
before do
|
101
|
-
reaper.schedule_kill_cursor(cursor_kill_spec_1
|
105
|
+
reaper.schedule_kill_cursor(cursor_kill_spec_1)
|
102
106
|
end
|
103
107
|
|
104
108
|
it 'does not add the kill cursors op spec to the list' do
|
@@ -189,8 +193,11 @@ describe Mongo::Cluster::CursorReaper do
|
|
189
193
|
around do |example|
|
190
194
|
authorized_collection.insert_many(docs)
|
191
195
|
periodic_executor.stop!
|
192
|
-
cluster.schedule_kill_cursor(
|
193
|
-
|
196
|
+
cluster.schedule_kill_cursor(
|
197
|
+
cursor.kill_spec(
|
198
|
+
cursor.instance_variable_get(:@server)
|
199
|
+
)
|
200
|
+
)
|
194
201
|
periodic_executor.flush
|
195
202
|
example.run
|
196
203
|
periodic_executor.run!
|