mongo 2.13.2 → 2.13.3
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/lib/mongo/collection.rb +2 -0
- data/lib/mongo/database.rb +14 -2
- data/lib/mongo/grid/fs_bucket.rb +37 -37
- data/lib/mongo/operation/parallel_scan/command.rb +1 -2
- data/lib/mongo/operation/shared/read_preference_supported.rb +38 -36
- data/lib/mongo/operation/shared/sessions_supported.rb +3 -2
- data/lib/mongo/protocol/msg.rb +2 -2
- data/lib/mongo/protocol/query.rb +11 -11
- data/lib/mongo/server_selector/secondary_preferred.rb +2 -7
- data/lib/mongo/version.rb +1 -1
- data/spec/integration/sdam_error_handling_spec.rb +1 -1
- data/spec/integration/sdam_events_spec.rb +3 -5
- data/spec/integration/secondary_reads_spec.rb +102 -0
- data/spec/mongo/index/view_spec.rb +4 -2
- data/spec/mongo/operation/read_preference_legacy_spec.rb +9 -19
- data/spec/mongo/operation/read_preference_op_msg_spec.rb +3 -3
- data/spec/mongo/server/app_metadata_shared.rb +33 -7
- data/spec/mongo/server_selector/secondary_preferred_spec.rb +6 -6
- data/spec/runners/transactions/operation.rb +13 -2
- data/spec/shared/bin/get-mongodb-download-url +17 -0
- data/spec/shared/lib/mrss/cluster_config.rb +221 -0
- data/spec/shared/lib/mrss/constraints.rb +43 -0
- data/spec/shared/lib/mrss/docker_runner.rb +265 -0
- data/spec/shared/lib/mrss/lite_constraints.rb +16 -0
- data/spec/shared/lib/mrss/server_version_registry.rb +115 -0
- data/spec/shared/lib/mrss/spec_organizer.rb +3 -0
- data/spec/shared/lib/mrss/utils.rb +15 -0
- data/spec/shared/share/Dockerfile.erb +231 -0
- data/spec/shared/shlib/distro.sh +73 -0
- data/spec/shared/shlib/server.sh +290 -0
- data/spec/shared/shlib/set_env.sh +128 -0
- data/spec/support/client_registry.rb +8 -4
- data/spec/support/client_registry_macros.rb +14 -5
- data/spec/support/spec_config.rb +12 -0
- data/spec/support/spec_setup.rb +48 -38
- data.tar.gz.sig +0 -0
- metadata +998 -978
- metadata.gz.sig +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 41f37eb33cbd1ebf2c916187b4610eefd895885042eeb3949882ce0a8c4ed069
|
4
|
+
data.tar.gz: db734108633f8b5988eaa15de33165182233ba5064f0b805298747256fb578b1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 27c0c7ca84b6b7983767eb652f6aa5968362d8b42a4adf3eab3ee4a11fe4e74d36096b636436ac5075b31207470a67a8c5ecb00eac7f27a3889966ee30d84db9
|
7
|
+
data.tar.gz: 86c9fb09b3fb9c9512db2e7caed2f21ac2d53ee75f671d1cbcc92b89afa0d471cc1217552c3971ee9641f90b4c710692ab885c454f8701371726623e16114604
|
checksums.yaml.gz.sig
CHANGED
Binary file
|
data/lib/mongo/collection.rb
CHANGED
@@ -573,6 +573,8 @@ module Mongo
|
|
573
573
|
# @param [ Array<Hash> ] documents The documents to insert.
|
574
574
|
# @param [ Hash ] options The insert options.
|
575
575
|
#
|
576
|
+
# @option options [ true | false ] :ordered Whether the operations
|
577
|
+
# should be executed in order.
|
576
578
|
# @option options [ Session ] :session The session to use for the operation.
|
577
579
|
#
|
578
580
|
# @return [ Result ] The database response wrapper.
|
data/lib/mongo/database.rb
CHANGED
@@ -315,8 +315,20 @@ module Mongo
|
|
315
315
|
|
316
316
|
# Get the Grid "filesystem" for this database.
|
317
317
|
#
|
318
|
-
# @
|
319
|
-
#
|
318
|
+
# @param [ Hash ] options The GridFS options.
|
319
|
+
#
|
320
|
+
# @option options [ String ] :bucket_name The prefix for the files and chunks
|
321
|
+
# collections.
|
322
|
+
# @option options [ Integer ] :chunk_size Override the default chunk
|
323
|
+
# size.
|
324
|
+
# @option options [ String ] :fs_name The prefix for the files and chunks
|
325
|
+
# collections.
|
326
|
+
# @option options [ String ] :read The read preference.
|
327
|
+
# @option options [ Session ] :session The session to use.
|
328
|
+
# @option options [ Hash ] :write Deprecated. Equivalent to :write_concern
|
329
|
+
# option.
|
330
|
+
# @option options [ Hash ] :write_concern The write concern options.
|
331
|
+
# Can be :w => Integer|String, :fsync => Boolean, :j => Boolean.
|
320
332
|
#
|
321
333
|
# @return [ Grid::FSBucket ] The GridFS for the database.
|
322
334
|
#
|
data/lib/mongo/grid/fs_bucket.rb
CHANGED
@@ -36,6 +36,43 @@ module Mongo
|
|
36
36
|
# @since 2.1.0
|
37
37
|
FILES_INDEX = { filename: 1, uploadDate: 1 }.freeze
|
38
38
|
|
39
|
+
# Create the GridFS.
|
40
|
+
#
|
41
|
+
# @example Create the GridFS.
|
42
|
+
# Grid::FSBucket.new(database)
|
43
|
+
#
|
44
|
+
# @param [ Database ] database The database the files reside in.
|
45
|
+
# @param [ Hash ] options The GridFS options.
|
46
|
+
#
|
47
|
+
# @option options [ String ] :bucket_name The prefix for the files and chunks
|
48
|
+
# collections.
|
49
|
+
# @option options [ Integer ] :chunk_size Override the default chunk
|
50
|
+
# size.
|
51
|
+
# @option options [ String ] :fs_name The prefix for the files and chunks
|
52
|
+
# collections.
|
53
|
+
# @option options [ String ] :read The read preference.
|
54
|
+
# @option options [ Session ] :session The session to use.
|
55
|
+
# @option options [ Hash ] :write Deprecated. Equivalent to :write_concern
|
56
|
+
# option.
|
57
|
+
# @option options [ Hash ] :write_concern The write concern options.
|
58
|
+
# Can be :w => Integer|String, :fsync => Boolean, :j => Boolean.
|
59
|
+
#
|
60
|
+
# @since 2.0.0
|
61
|
+
def initialize(database, options = {})
|
62
|
+
@database = database
|
63
|
+
@options = options.dup
|
64
|
+
=begin WriteConcern object support
|
65
|
+
if @options[:write_concern].is_a?(WriteConcern::Base)
|
66
|
+
# Cache the instance so that we do not needlessly reconstruct it.
|
67
|
+
@write_concern = @options[:write_concern]
|
68
|
+
@options[:write_concern] = @write_concern.options
|
69
|
+
end
|
70
|
+
=end
|
71
|
+
@options.freeze
|
72
|
+
@chunks_collection = database[chunks_name]
|
73
|
+
@files_collection = database[files_name]
|
74
|
+
end
|
75
|
+
|
39
76
|
# @return [ Collection ] chunks_collection The chunks collection.
|
40
77
|
#
|
41
78
|
# @since 2.0.0
|
@@ -133,43 +170,6 @@ module Mongo
|
|
133
170
|
file.id
|
134
171
|
end
|
135
172
|
|
136
|
-
# Create the GridFS.
|
137
|
-
#
|
138
|
-
# @example Create the GridFS.
|
139
|
-
# Grid::FSBucket.new(database)
|
140
|
-
#
|
141
|
-
# @param [ Database ] database The database the files reside in.
|
142
|
-
# @param [ Hash ] options The GridFS options.
|
143
|
-
#
|
144
|
-
# @option options [ String ] :fs_name The prefix for the files and chunks
|
145
|
-
# collections.
|
146
|
-
# @option options [ String ] :bucket_name The prefix for the files and chunks
|
147
|
-
# collections.
|
148
|
-
# @option options [ Integer ] :chunk_size Override the default chunk
|
149
|
-
# size.
|
150
|
-
# @option options [ String ] :read The read preference.
|
151
|
-
# @option options [ Session ] :session The session to use.
|
152
|
-
# @option options [ Hash ] :write Deprecated. Equivalent to :write_concern
|
153
|
-
# option.
|
154
|
-
# @option options [ Hash ] :write_concern The write concern options.
|
155
|
-
# Can be :w => Integer|String, :fsync => Boolean, :j => Boolean.
|
156
|
-
#
|
157
|
-
# @since 2.0.0
|
158
|
-
def initialize(database, options = {})
|
159
|
-
@database = database
|
160
|
-
@options = options.dup
|
161
|
-
=begin WriteConcern object support
|
162
|
-
if @options[:write_concern].is_a?(WriteConcern::Base)
|
163
|
-
# Cache the instance so that we do not needlessly reconstruct it.
|
164
|
-
@write_concern = @options[:write_concern]
|
165
|
-
@options[:write_concern] = @write_concern.options
|
166
|
-
end
|
167
|
-
=end
|
168
|
-
@options.freeze
|
169
|
-
@chunks_collection = database[chunks_name]
|
170
|
-
@files_collection = database[files_name]
|
171
|
-
end
|
172
|
-
|
173
173
|
# Get the prefix for the GridFS
|
174
174
|
#
|
175
175
|
# @example Get the prefix.
|
@@ -36,47 +36,44 @@ module Mongo
|
|
36
36
|
#
|
37
37
|
# @since 2.0.0
|
38
38
|
def options(connection)
|
39
|
-
|
39
|
+
options = super
|
40
|
+
if add_slave_ok_flag?(connection)
|
41
|
+
flags = options[:flags]&.dup || []
|
42
|
+
flags << :slave_ok
|
43
|
+
options = options.merge(flags: flags)
|
44
|
+
end
|
45
|
+
options
|
40
46
|
end
|
41
47
|
|
42
|
-
#
|
43
|
-
# in the operation or implied by the topology
|
44
|
-
# server is a part of.
|
48
|
+
# Whether to add the :slave_ok flag to the request based on the
|
49
|
+
# read preference specified in the operation or implied by the topology
|
50
|
+
# that the connection's server is a part of.
|
45
51
|
#
|
46
|
-
# @param [ Hash ] options The options calculated so far.
|
47
52
|
# @param [ Server::Connection ] connection The connection that the
|
48
53
|
# operation will be executed on.
|
49
54
|
#
|
50
|
-
# @return [
|
51
|
-
def
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
read && read.slave_ok?
|
67
|
-
end
|
68
|
-
|
69
|
-
if add_flag
|
70
|
-
options= options.dup
|
71
|
-
(options[:flags] ||= []) << :slave_ok
|
55
|
+
# @return [ true | false ] Whether the :slave_ok flag should be added.
|
56
|
+
def add_slave_ok_flag?(connection)
|
57
|
+
# https://github.com/mongodb/specifications/blob/master/source/server-selection/server-selection.rst#topology-type-single
|
58
|
+
if connection.description.standalone?
|
59
|
+
# Read preference is never sent to standalones.
|
60
|
+
false
|
61
|
+
elsif connection.server.cluster.single?
|
62
|
+
# In Single topology the driver forces primaryPreferred read
|
63
|
+
# preference mode (via the slave_ok flag, in case of old servers)
|
64
|
+
# so that the query is satisfied.
|
65
|
+
true
|
66
|
+
else
|
67
|
+
# In replica sets and sharded clusters, read preference is passed
|
68
|
+
# to the server if one is specified by the application, and there
|
69
|
+
# is no default.
|
70
|
+
read && read.slave_ok? || false
|
72
71
|
end
|
73
|
-
|
74
|
-
options
|
75
72
|
end
|
76
73
|
|
77
74
|
def command(connection)
|
78
75
|
sel = super
|
79
|
-
|
76
|
+
add_read_preference_legacy(sel, connection)
|
80
77
|
end
|
81
78
|
|
82
79
|
# Adds $readPreference field to the command document.
|
@@ -95,14 +92,19 @@ module Mongo
|
|
95
92
|
# operation will be executed on.
|
96
93
|
#
|
97
94
|
# @return [ Hash ] New command document to send to the server.
|
98
|
-
def
|
95
|
+
def add_read_preference_legacy(sel, connection)
|
99
96
|
if read && connection.description.mongos? && read_pref = read.to_mongos
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
97
|
+
# If the read preference contains only mode and mode is secondary
|
98
|
+
# preferred and we are sending to a pre-OP_MSG server, this read
|
99
|
+
# preference is indicated by the :slave_ok wire protocol flag
|
100
|
+
# and $readPreference command parameter isn't sent.
|
101
|
+
if read_pref != {mode: 'secondaryPreferred'}
|
102
|
+
Mongo::Lint.validate_camel_case_read_preference(read_pref)
|
103
|
+
sel = sel[:$query] ? sel : {:$query => sel}
|
104
|
+
sel = sel.merge(:$readPreference => read_pref)
|
105
|
+
end
|
105
106
|
end
|
107
|
+
sel
|
106
108
|
end
|
107
109
|
end
|
108
110
|
end
|
@@ -170,9 +170,10 @@ module Mongo
|
|
170
170
|
elsif connection.description.mongos?
|
171
171
|
# When server is a mongos:
|
172
172
|
# - $readPreference is never sent when mode is 'primary'
|
173
|
-
# - When mode is 'secondaryPreferred' $readPreference is only sent
|
174
|
-
# when a non-mode field (i.e. tag_sets) is present
|
175
173
|
# - Otherwise $readPreference is sent
|
174
|
+
# When mode is 'secondaryPreferred' $readPreference is currently
|
175
|
+
# required to only be sent when a non-mode field (i.e. tag_sets)
|
176
|
+
# is present, but this causes wrong behavior (DRIVERS-1642).
|
176
177
|
if read
|
177
178
|
doc = read.to_mongos
|
178
179
|
if doc
|
data/lib/mongo/protocol/msg.rb
CHANGED
@@ -43,8 +43,8 @@ module Mongo
|
|
43
43
|
# Msg.new([:more_to_come], {}, { ismaster: 1 },
|
44
44
|
# { type: 1, payload: { identifier: 'documents', sequence: [..] } })
|
45
45
|
#
|
46
|
-
# @param [ Array<Symbol> ] flags The flag bits.
|
47
|
-
# are :more_to_come and :checksum_present.
|
46
|
+
# @param [ Array<Symbol> ] flags The flag bits. Currently supported
|
47
|
+
# values are :more_to_come and :checksum_present.
|
48
48
|
# @param [ Hash ] options The options.
|
49
49
|
# @param [ BSON::Document, Hash ] main_document The document that will
|
50
50
|
# become the payload type 0 section. Can contain global args as they
|
data/lib/mongo/protocol/query.rb
CHANGED
@@ -46,18 +46,18 @@ module Mongo
|
|
46
46
|
# @example Find all user ids.
|
47
47
|
# Query.new('xgen', 'users', {}, :fields => {:id => 1})
|
48
48
|
#
|
49
|
-
# @param
|
50
|
-
# @param
|
51
|
-
# @param
|
52
|
-
# @param
|
49
|
+
# @param [ String, Symbol ] database The database to query.
|
50
|
+
# @param [ String, Symbol ] collection The collection to query.
|
51
|
+
# @param [ Hash ] selector The query selector.
|
52
|
+
# @param [ Hash ] options The additional query options.
|
53
53
|
#
|
54
|
-
# @option options
|
55
|
-
#
|
56
|
-
#
|
57
|
-
#
|
58
|
-
#
|
59
|
-
#
|
60
|
-
#
|
54
|
+
# @option options [ Array<Symbol> ] :flags The flag bits.
|
55
|
+
# Currently supported values are :await_data, :exhaust,
|
56
|
+
# :no_cursor_timeout, :oplog_replay, :partial, :slave_ok,
|
57
|
+
# :tailable_cursor.
|
58
|
+
# @option options [ Integer ] :limit The number of documents to return.
|
59
|
+
# @option options [ Hash ] :project The projection.
|
60
|
+
# @option options [ Integer ] :skip The number of documents to skip.
|
61
61
|
def initialize(database, collection, selector, options = {})
|
62
62
|
@database = database
|
63
63
|
@namespace = "#{database}.#{collection}"
|
@@ -86,13 +86,8 @@ module Mongo
|
|
86
86
|
#
|
87
87
|
# @since 2.0.0
|
88
88
|
def to_mongos
|
89
|
-
|
90
|
-
|
91
|
-
# selector if there are no tag sets, for maximum backwards compatibility.
|
92
|
-
nil
|
93
|
-
else
|
94
|
-
to_doc
|
95
|
-
end
|
89
|
+
# Always send the read preference to mongos: DRIVERS-1642.
|
90
|
+
to_doc
|
96
91
|
end
|
97
92
|
|
98
93
|
private
|
data/lib/mongo/version.rb
CHANGED
@@ -67,10 +67,8 @@ describe 'SDAM events' do
|
|
67
67
|
started_events.length.should <= 10
|
68
68
|
|
69
69
|
succeeded_events = subscriber.select_succeeded_events(Mongo::Monitoring::Event::ServerHeartbeatSucceeded)
|
70
|
-
# Since we gracefully close the client, we expect each heartbeat
|
71
|
-
# to complete.
|
72
70
|
started_events.length.should > 1
|
73
|
-
(succeeded_events.length
|
71
|
+
(succeeded_events.length..succeeded_events.length+1).should include(started_events.length)
|
74
72
|
end
|
75
73
|
end
|
76
74
|
|
@@ -109,9 +107,9 @@ describe 'SDAM events' do
|
|
109
107
|
# There may be in-flight ismasters that don't complete, both
|
110
108
|
# regular and awaited.
|
111
109
|
started_awaited.length.should > 1
|
112
|
-
(succeeded_awaited.length
|
110
|
+
(succeeded_awaited.length..succeeded_awaited.length+1).should include(started_awaited.length)
|
113
111
|
started_regular.length.should > 1
|
114
|
-
(succeeded_regular.length
|
112
|
+
(succeeded_regular.length..succeeded_regular.length+1).should include(started_regular.length)
|
115
113
|
end
|
116
114
|
end
|
117
115
|
end
|
@@ -0,0 +1,102 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'Secondary reads' do
|
4
|
+
before do
|
5
|
+
root_authorized_client.use('sr')['secondary_reads'].drop
|
6
|
+
root_authorized_client.use('sr')['secondary_reads'].insert_one(test: 1)
|
7
|
+
end
|
8
|
+
|
9
|
+
shared_examples 'performs reads as per read preference' do
|
10
|
+
|
11
|
+
%i(primary primary_preferred).each do |mode|
|
12
|
+
|
13
|
+
context mode.inspect do
|
14
|
+
|
15
|
+
let(:client) do
|
16
|
+
root_authorized_client.with(read: {mode: mode}).use('sr')
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'reads from primary' do
|
20
|
+
start_stats = get_read_counters
|
21
|
+
|
22
|
+
30.times do
|
23
|
+
client['secondary_reads'].find.to_a
|
24
|
+
end
|
25
|
+
|
26
|
+
end_stats = get_read_counters
|
27
|
+
|
28
|
+
end_stats[:secondary].should be_within(10).of(start_stats[:secondary])
|
29
|
+
end_stats[:primary].should >= start_stats[:primary] + 30
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
%i(secondary secondary_preferred).each do |mode|
|
35
|
+
|
36
|
+
context mode.inspect do
|
37
|
+
let(:client) do
|
38
|
+
root_authorized_client.with(read: {mode: mode}).use('sr')
|
39
|
+
end
|
40
|
+
|
41
|
+
it 'reads from secondaries' do
|
42
|
+
start_stats = get_read_counters
|
43
|
+
|
44
|
+
30.times do
|
45
|
+
client['secondary_reads'].find.to_a
|
46
|
+
end
|
47
|
+
|
48
|
+
end_stats = get_read_counters
|
49
|
+
|
50
|
+
end_stats[:primary].should be_within(10).of(start_stats[:primary])
|
51
|
+
end_stats[:secondary].should >= start_stats[:secondary] + 30
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
context 'replica set' do
|
58
|
+
require_topology :replica_set
|
59
|
+
|
60
|
+
include_examples 'performs reads as per read preference'
|
61
|
+
end
|
62
|
+
|
63
|
+
context 'sharded cluster' do
|
64
|
+
require_topology :sharded
|
65
|
+
|
66
|
+
include_examples 'performs reads as per read preference'
|
67
|
+
end
|
68
|
+
|
69
|
+
def get_read_counters
|
70
|
+
client = ClientRegistry.instance.global_client('root_authorized')
|
71
|
+
addresses = []
|
72
|
+
if client.cluster.sharded?
|
73
|
+
doc = client.use('admin').command(listShards: 1).documents.first
|
74
|
+
doc['shards'].each do |shard|
|
75
|
+
addresses += shard['host'].split('/').last.split(',')
|
76
|
+
end
|
77
|
+
else
|
78
|
+
client.cluster.servers.each do |server|
|
79
|
+
next unless server.primary? || server.secondary?
|
80
|
+
addresses << server.address.seed
|
81
|
+
end
|
82
|
+
end
|
83
|
+
stats = Hash.new(0)
|
84
|
+
addresses.each do |address|
|
85
|
+
ClientRegistry.instance.new_local_client(
|
86
|
+
[address],
|
87
|
+
SpecConfig.instance.all_test_options.merge(connect: :direct),
|
88
|
+
) do |c|
|
89
|
+
server = c.cluster.servers.first
|
90
|
+
next unless server.primary? || server.secondary?
|
91
|
+
stat = c.command(serverStatus: 1).documents.first
|
92
|
+
queries = stat['opcounters']['query']
|
93
|
+
if server.primary?
|
94
|
+
stats[:primary] += queries
|
95
|
+
else
|
96
|
+
stats[:secondary] += queries
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
stats
|
101
|
+
end
|
102
|
+
end
|