mongo 2.11.0 → 2.11.5
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/Rakefile +24 -0
- data/lib/mongo/address.rb +53 -37
- data/lib/mongo/auth.rb +30 -10
- data/lib/mongo/auth/cr.rb +1 -0
- data/lib/mongo/auth/cr/conversation.rb +13 -13
- data/lib/mongo/auth/ldap.rb +2 -1
- data/lib/mongo/auth/ldap/conversation.rb +9 -12
- data/lib/mongo/auth/scram.rb +1 -0
- data/lib/mongo/auth/scram/conversation.rb +36 -27
- data/lib/mongo/auth/user.rb +7 -1
- data/lib/mongo/auth/x509.rb +2 -1
- data/lib/mongo/auth/x509/conversation.rb +9 -9
- data/lib/mongo/bulk_write/transformable.rb +3 -3
- data/lib/mongo/client.rb +17 -6
- data/lib/mongo/cluster.rb +67 -49
- data/lib/mongo/cluster/sdam_flow.rb +87 -3
- data/lib/mongo/collection/view/readable.rb +3 -1
- data/lib/mongo/collection/view/writable.rb +3 -3
- data/lib/mongo/cursor/builder/kill_cursors_command.rb +8 -1
- data/lib/mongo/cursor/builder/op_kill_cursors.rb +8 -1
- data/lib/mongo/database.rb +1 -1
- data/lib/mongo/grid/file.rb +5 -0
- data/lib/mongo/grid/file/chunk.rb +2 -0
- data/lib/mongo/grid/fs_bucket.rb +15 -13
- data/lib/mongo/grid/stream/write.rb +9 -3
- data/lib/mongo/protocol/serializers.rb +12 -2
- data/lib/mongo/retryable.rb +33 -8
- data/lib/mongo/server.rb +13 -6
- data/lib/mongo/server/connection.rb +15 -8
- data/lib/mongo/server/connection_base.rb +7 -4
- data/lib/mongo/server/description.rb +34 -21
- data/lib/mongo/server/monitor.rb +1 -1
- data/lib/mongo/server/monitor/connection.rb +2 -3
- data/lib/mongo/session.rb +10 -10
- data/lib/mongo/socket.rb +10 -1
- data/lib/mongo/uri.rb +1 -1
- data/lib/mongo/version.rb +1 -1
- data/mongo.gemspec +1 -1
- data/spec/README.md +13 -0
- data/spec/integration/auth_spec.rb +27 -8
- data/spec/integration/bson_symbol_spec.rb +34 -0
- data/spec/integration/client_construction_spec.rb +14 -0
- data/spec/integration/client_options_spec.rb +5 -5
- data/spec/integration/connection_spec.rb +57 -9
- data/spec/integration/crud_spec.rb +45 -0
- data/spec/integration/cursor_reaping_spec.rb +2 -1
- data/spec/integration/grid_fs_bucket_spec.rb +48 -0
- data/spec/integration/retryable_errors_spec.rb +204 -39
- data/spec/integration/retryable_writes_spec.rb +36 -36
- data/spec/integration/size_limit_spec.rb~12e1e9c4f... RUBY-2242 Fix zlib compression (#2021) +98 -0
- data/spec/lite_spec_helper.rb +1 -0
- data/spec/mongo/address_spec.rb +19 -13
- data/spec/mongo/auth/ldap/conversation_spec.rb +1 -1
- data/spec/mongo/auth/scram/conversation_spec.rb +25 -14
- data/spec/mongo/auth/user/view_spec.rb +36 -1
- data/spec/mongo/auth/user_spec.rb +12 -0
- data/spec/mongo/auth/x509/conversation_spec.rb +1 -1
- data/spec/mongo/bulk_write_spec.rb +2 -2
- data/spec/mongo/client_construction_spec.rb +1 -21
- data/spec/mongo/cluster_spec.rb +57 -0
- data/spec/mongo/collection/view/map_reduce_spec.rb +1 -1
- data/spec/mongo/collection_spec.rb +26 -2
- data/spec/mongo/cursor/builder/op_kill_cursors_spec.rb +56 -0
- data/spec/mongo/server/connection_spec.rb +76 -8
- data/spec/mongo/server/monitor/connection_spec.rb +14 -7
- data/spec/mongo/socket/ssl_spec.rb +132 -98
- data/spec/mongo/socket/tcp_spec.rb +1 -9
- data/spec/mongo/uri_spec.rb +1 -1
- data/spec/runners/sdam/verifier.rb +91 -0
- data/spec/spec_tests/data/sdam/rs/primary_address_change.yml +29 -0
- data/spec/spec_tests/data/sdam/rs/primary_mismatched_me.yml +27 -23
- data/spec/spec_tests/data/sdam/rs/primary_to_no_primary_mismatched_me.yml +56 -79
- data/spec/spec_tests/data/sdam/sharded/primary_address_change.yml +21 -0
- data/spec/spec_tests/data/sdam/sharded/primary_mismatched_me.yml +22 -0
- data/spec/spec_tests/data/sdam/single/primary_address_change.yml +24 -0
- data/spec/spec_tests/data/sdam/single/primary_mismatched_me.yml +25 -0
- data/spec/spec_tests/data/sdam_monitoring/replica_set_with_me_mismatch.yml +159 -0
- data/spec/spec_tests/data/sdam_monitoring/{replica_set_other_seed.yml → replica_set_with_primary_change.yml} +97 -101
- data/spec/spec_tests/data/sdam_monitoring/replica_set_with_primary_removal.yml +22 -18
- data/spec/spec_tests/data/sdam_monitoring/standalone_to_rs_with_me_mismatch.yml +90 -0
- data/spec/spec_tests/sdam_monitoring_spec.rb +9 -4
- data/spec/support/cluster_config.rb +36 -0
- data/spec/support/cluster_tools.rb +5 -3
- data/spec/support/command_monitoring.rb +1 -1
- data/spec/support/constraints.rb +18 -18
- data/spec/support/lite_constraints.rb +8 -0
- data/spec/support/sdam_monitoring.rb +0 -115
- data/spec/support/server_discovery_and_monitoring.rb +2 -0
- data/spec/support/spec_config.rb +1 -1
- data/spec/support/utils.rb +11 -1
- metadata +687 -659
- metadata.gz.sig +3 -2
@@ -82,6 +82,20 @@ describe 'Client construction' do
|
|
82
82
|
expect(client.cluster.topology).to be_a(Mongo::Cluster::Topology::Single)
|
83
83
|
expect(client.options[:connect]).to eq :direct
|
84
84
|
end
|
85
|
+
|
86
|
+
context 'direct connection with mismached me' do
|
87
|
+
let(:address) { ClusterConfig.instance.alternate_address.to_s }
|
88
|
+
|
89
|
+
let(:client) do
|
90
|
+
new_local_client([address], SpecConfig.instance.test_options)
|
91
|
+
end
|
92
|
+
|
93
|
+
let(:server) { client.cluster.next_primary }
|
94
|
+
|
95
|
+
it 'sets server type to primary' do
|
96
|
+
expect(server.description).to be_primary
|
97
|
+
end
|
98
|
+
end
|
85
99
|
end
|
86
100
|
|
87
101
|
context 'in sharded topology' do
|
@@ -38,7 +38,7 @@ describe 'Client options' do
|
|
38
38
|
end
|
39
39
|
end
|
40
40
|
|
41
|
-
shared_examples_for 'auth mechanism that uses database or default auth source' do |default_auth_source
|
41
|
+
shared_examples_for 'auth mechanism that uses database or default auth source' do |default_auth_source|
|
42
42
|
context 'where no database is provided' do
|
43
43
|
context 'with URI options' do
|
44
44
|
let(:credentials) { "#{user}:#{pwd}@" }
|
@@ -198,7 +198,7 @@ describe 'Client options' do
|
|
198
198
|
let(:auth_mech_sym) { :mongodb_cr }
|
199
199
|
|
200
200
|
it_behaves_like 'a supported auth mechanism'
|
201
|
-
it_behaves_like 'auth mechanism that uses database or default auth source',
|
201
|
+
it_behaves_like 'auth mechanism that uses database or default auth source', 'admin'
|
202
202
|
it_behaves_like 'an auth mechanism that doesn\'t support auth_mech_properties'
|
203
203
|
end
|
204
204
|
|
@@ -207,7 +207,7 @@ describe 'Client options' do
|
|
207
207
|
let(:auth_mech_sym) { :scram }
|
208
208
|
|
209
209
|
it_behaves_like 'a supported auth mechanism'
|
210
|
-
it_behaves_like 'auth mechanism that uses database or default auth source',
|
210
|
+
it_behaves_like 'auth mechanism that uses database or default auth source', 'admin'
|
211
211
|
it_behaves_like 'an auth mechanism that doesn\'t support auth_mech_properties'
|
212
212
|
end
|
213
213
|
|
@@ -216,7 +216,7 @@ describe 'Client options' do
|
|
216
216
|
let(:auth_mech_sym) { :scram256 }
|
217
217
|
|
218
218
|
it_behaves_like 'a supported auth mechanism'
|
219
|
-
it_behaves_like 'auth mechanism that uses database or default auth source',
|
219
|
+
it_behaves_like 'auth mechanism that uses database or default auth source', 'admin'
|
220
220
|
it_behaves_like 'an auth mechanism that doesn\'t support auth_mech_properties'
|
221
221
|
end
|
222
222
|
|
@@ -263,7 +263,7 @@ describe 'Client options' do
|
|
263
263
|
let(:auth_mech_sym) { :plain }
|
264
264
|
|
265
265
|
it_behaves_like 'a supported auth mechanism'
|
266
|
-
it_behaves_like 'auth mechanism that uses database or default auth source',
|
266
|
+
it_behaves_like 'auth mechanism that uses database or default auth source', '$external'
|
267
267
|
it_behaves_like 'an auth mechanism with ssl'
|
268
268
|
it_behaves_like 'an auth mechanism that doesn\'t support auth_mech_properties'
|
269
269
|
end
|
@@ -12,17 +12,18 @@ describe 'Connections' do
|
|
12
12
|
let(:server) { client.cluster.servers.first }
|
13
13
|
|
14
14
|
describe '#connect!' do
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
# RSpec::Expectations::ExpectationNotMetError: expected Mongo::Error::SocketError, got #<NameError: undefined method `write' for class `Mongo::Socket'>
|
20
|
-
fails_on_jruby
|
15
|
+
|
16
|
+
let(:connection) do
|
17
|
+
Mongo::Server::Connection.new(server, server.options)
|
18
|
+
end
|
21
19
|
|
22
20
|
context 'network error during handshake' do
|
23
|
-
|
24
|
-
|
25
|
-
|
21
|
+
# On JRuby 9.2.7.0, this line:
|
22
|
+
# expect_any_instance_of(Mongo::Socket).to receive(:write).and_raise(exception)
|
23
|
+
# ... appears to produce a moment in which Mongo::Socket#write is undefined
|
24
|
+
# entirely, resulting in this failure:
|
25
|
+
# RSpec::Expectations::ExpectationNotMetError: expected Mongo::Error::SocketError, got #<NameError: undefined method `write' for class `Mongo::Socket'>
|
26
|
+
fails_on_jruby
|
26
27
|
|
27
28
|
let(:exception) { Mongo::Error::SocketError }
|
28
29
|
|
@@ -120,6 +121,53 @@ describe 'Connections' do
|
|
120
121
|
expect(client.cluster.topology).to be_a(Mongo::Cluster::Topology::ReplicaSetNoPrimary)
|
121
122
|
end
|
122
123
|
end
|
124
|
+
|
125
|
+
describe 'number of sockets created' do
|
126
|
+
|
127
|
+
before do
|
128
|
+
server
|
129
|
+
end
|
130
|
+
|
131
|
+
shared_examples_for 'is 1 per connection' do
|
132
|
+
it 'is 1 per connection' do
|
133
|
+
# Instantiating a connection object should not create any sockets
|
134
|
+
RSpec::Mocks.with_temporary_scope do
|
135
|
+
expect(socket_cls).not_to receive(:new)
|
136
|
+
|
137
|
+
connection
|
138
|
+
end
|
139
|
+
|
140
|
+
# When the connection connects, exactly one socket should be created
|
141
|
+
# (and subsequently connected)
|
142
|
+
RSpec::Mocks.with_temporary_scope do
|
143
|
+
expect(socket_cls).to receive(:new).and_call_original
|
144
|
+
|
145
|
+
connection.connect!
|
146
|
+
end
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
let(:socket_cls) { ::Socket }
|
151
|
+
|
152
|
+
it_behaves_like 'is 1 per connection'
|
153
|
+
|
154
|
+
context 'connection to Unix domain socket' do
|
155
|
+
# Server does not allow Unix socket connections when TLS is enabled
|
156
|
+
require_no_tls
|
157
|
+
|
158
|
+
let(:port) { SpecConfig.instance.any_port }
|
159
|
+
|
160
|
+
let(:client) do
|
161
|
+
new_local_client(["/tmp/mongodb-#{port}.sock"], connect: :direct).tap do |client|
|
162
|
+
stop_monitoring(client)
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
let(:socket_cls) { ::UNIXSocket }
|
167
|
+
|
168
|
+
it_behaves_like 'is 1 per connection'
|
169
|
+
end
|
170
|
+
end
|
123
171
|
end
|
124
172
|
|
125
173
|
describe 'wire protocol version range update' do
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'CRUD operations' do
|
4
|
+
let(:collection) { authorized_client['crud_integration'] }
|
5
|
+
|
6
|
+
before do
|
7
|
+
collection.delete_many
|
8
|
+
end
|
9
|
+
|
10
|
+
describe 'upsert' do
|
11
|
+
context 'with default write concern' do
|
12
|
+
it 'upserts' do
|
13
|
+
collection.count_documents({}).should == 0
|
14
|
+
|
15
|
+
res = collection.find(_id: 'foo').update_one({'$set' => {foo: 'bar'}}, upsert: true)
|
16
|
+
|
17
|
+
res.documents.first['upserted'].length.should == 1
|
18
|
+
|
19
|
+
collection.count_documents({}).should == 1
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
context 'unacknowledged write' do
|
24
|
+
let(:unack_collection) do
|
25
|
+
collection.with(write_concern: {w: 0})
|
26
|
+
end
|
27
|
+
|
28
|
+
before do
|
29
|
+
unack_collection.write_concern.acknowledged?.should be false
|
30
|
+
end
|
31
|
+
|
32
|
+
it 'upserts' do
|
33
|
+
unack_collection.count_documents({}).should == 0
|
34
|
+
|
35
|
+
res = unack_collection.find(_id: 'foo').update_one({'$set' => {foo: 'bar'}}, upsert: true)
|
36
|
+
|
37
|
+
# since write concern is unacknowledged, wait for the data to be
|
38
|
+
# persisted (hopefully)
|
39
|
+
sleep 0.25
|
40
|
+
|
41
|
+
unack_collection.count_documents({}).should == 1
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -59,7 +59,8 @@ describe 'Cursor reaping' do
|
|
59
59
|
client.cluster.instance_variable_get('@periodic_executor').execute
|
60
60
|
|
61
61
|
started_event = EventSubscriber.started_events.detect do |event|
|
62
|
-
event.command['killCursors'] &&
|
62
|
+
event.command['killCursors'] &&
|
63
|
+
event.command['cursors'].map { |c| Utils.int64_value(c) }.include?(cursor_id)
|
63
64
|
end
|
64
65
|
|
65
66
|
expect(started_event).not_to be_nil
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'GridFS bucket integration' do
|
4
|
+
let(:fs) do
|
5
|
+
authorized_client.database.fs
|
6
|
+
end
|
7
|
+
|
8
|
+
describe 'UTF-8 string write' do
|
9
|
+
let(:data) { "hello\u2210" }
|
10
|
+
|
11
|
+
before do
|
12
|
+
data.length.should_not == data.bytesize
|
13
|
+
end
|
14
|
+
|
15
|
+
shared_examples 'round-trips' do
|
16
|
+
it 'round-trips' do
|
17
|
+
stream = fs.open_upload_stream('test') do |stream|
|
18
|
+
stream.write(data_to_write)
|
19
|
+
end
|
20
|
+
|
21
|
+
actual = nil
|
22
|
+
fs.open_download_stream(stream.file_id) do |stream|
|
23
|
+
actual = stream.read
|
24
|
+
end
|
25
|
+
|
26
|
+
actual.encoding.name.should == 'ASCII-8BIT'
|
27
|
+
actual.should == data.dup.force_encoding('binary')
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
context 'in binary encoding' do
|
32
|
+
let(:data_to_write) do
|
33
|
+
data.force_encoding('binary').freeze
|
34
|
+
end
|
35
|
+
|
36
|
+
it_behaves_like 'round-trips'
|
37
|
+
end
|
38
|
+
|
39
|
+
context 'in UTF-8 encoding' do
|
40
|
+
let(:data_to_write) do
|
41
|
+
data.encoding.name.should == 'UTF-8'
|
42
|
+
data.freeze
|
43
|
+
end
|
44
|
+
|
45
|
+
it_behaves_like 'round-trips'
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
describe '
|
3
|
+
describe 'Failing retryable operations' do
|
4
4
|
# Requirement for fail point
|
5
5
|
min_server_fcv '4.0'
|
6
6
|
|
@@ -9,22 +9,12 @@ describe 'Retryable writes tests' do
|
|
9
9
|
end
|
10
10
|
|
11
11
|
let(:collection) do
|
12
|
-
client['retryable-
|
12
|
+
client['retryable-errors-spec']
|
13
13
|
end
|
14
14
|
|
15
|
-
context 'when
|
15
|
+
context 'when operation fails' do
|
16
16
|
require_topology :replica_set
|
17
17
|
|
18
|
-
let(:fail_point_command) do
|
19
|
-
{
|
20
|
-
configureFailPoint: 'failCommand',
|
21
|
-
mode: {times: 1},
|
22
|
-
data: {
|
23
|
-
failCommands: ['find'],
|
24
|
-
errorCode: 11600,
|
25
|
-
},
|
26
|
-
}
|
27
|
-
end
|
28
18
|
|
29
19
|
let(:clear_fail_point_command) do
|
30
20
|
{
|
@@ -34,17 +24,13 @@ describe 'Retryable writes tests' do
|
|
34
24
|
end
|
35
25
|
|
36
26
|
after do
|
37
|
-
ClusterTools.instance.
|
27
|
+
ClusterTools.instance.direct_client_for_each_data_bearing_server do |client|
|
38
28
|
client.use(:admin).database.command(clear_fail_point_command)
|
39
29
|
end
|
40
30
|
end
|
41
31
|
|
42
32
|
let(:collection) do
|
43
|
-
client['retryable-
|
44
|
-
end
|
45
|
-
|
46
|
-
let(:events) do
|
47
|
-
events = EventSubscriber.command_started_events('find')
|
33
|
+
client['retryable-errors-spec', read: {mode: :secondary_preferred}]
|
48
34
|
end
|
49
35
|
|
50
36
|
let(:first_server) do
|
@@ -59,41 +45,220 @@ describe 'Retryable writes tests' do
|
|
59
45
|
end
|
60
46
|
end
|
61
47
|
|
62
|
-
|
63
|
-
|
64
|
-
|
48
|
+
shared_context 'read operation' do
|
49
|
+
let(:fail_point_command) do
|
50
|
+
{
|
51
|
+
configureFailPoint: 'failCommand',
|
52
|
+
mode: {times: 1},
|
53
|
+
data: {
|
54
|
+
failCommands: ['find'],
|
55
|
+
errorCode: 11600,
|
56
|
+
},
|
57
|
+
}
|
58
|
+
end
|
59
|
+
|
60
|
+
let(:set_fail_point) do
|
61
|
+
client.cluster.servers_list.each do |server|
|
62
|
+
server.monitor.stop!
|
63
|
+
end
|
64
|
+
|
65
|
+
ClusterTools.instance.direct_client_for_each_data_bearing_server do |client|
|
66
|
+
client.use(:admin).database.command(fail_point_command)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
let(:operation_exception) do
|
71
|
+
set_fail_point
|
72
|
+
|
73
|
+
begin
|
74
|
+
collection.find(a: 1).to_a
|
75
|
+
rescue Mongo::Error::OperationFailure => exception
|
76
|
+
else
|
77
|
+
fail('Expected operation to fail')
|
78
|
+
end
|
79
|
+
|
80
|
+
puts exception.message
|
81
|
+
|
82
|
+
exception
|
83
|
+
end
|
84
|
+
|
85
|
+
let(:events) do
|
86
|
+
EventSubscriber.command_started_events('find')
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
shared_context 'write operation' do
|
91
|
+
let(:fail_point_command) do
|
92
|
+
{
|
93
|
+
configureFailPoint: 'failCommand',
|
94
|
+
mode: {times: 2},
|
95
|
+
data: {
|
96
|
+
failCommands: ['insert'],
|
97
|
+
errorCode: 11600,
|
98
|
+
},
|
99
|
+
}
|
65
100
|
end
|
66
101
|
|
67
|
-
|
102
|
+
let(:set_fail_point) do
|
68
103
|
client.use(:admin).database.command(fail_point_command)
|
69
104
|
end
|
70
105
|
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
106
|
+
let(:operation_exception) do
|
107
|
+
set_fail_point
|
108
|
+
|
109
|
+
begin
|
110
|
+
collection.insert_one(a: 1)
|
111
|
+
rescue Mongo::Error::OperationFailure => exception
|
112
|
+
else
|
113
|
+
fail('Expected operation to fail')
|
114
|
+
end
|
115
|
+
|
116
|
+
#puts exception.message
|
117
|
+
|
118
|
+
exception
|
119
|
+
end
|
120
|
+
|
121
|
+
let(:events) do
|
122
|
+
EventSubscriber.command_started_events('insert')
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
shared_examples_for 'failing retry' do
|
127
|
+
|
128
|
+
it 'indicates second attempt' do
|
129
|
+
expect(operation_exception.message).to include('attempt 2')
|
130
|
+
expect(operation_exception.message).not_to include('attempt 1')
|
131
|
+
expect(operation_exception.message).not_to include('attempt 3')
|
132
|
+
end
|
133
|
+
|
134
|
+
it 'publishes two events' do
|
135
|
+
|
136
|
+
expect(events.length).to eq(2)
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
shared_examples_for 'failing single attempt' do
|
141
|
+
|
142
|
+
it 'does not indicate attempt' do
|
143
|
+
expect(operation_exception.message).not_to include('attempt 1')
|
144
|
+
expect(operation_exception.message).not_to include('attempt 2')
|
145
|
+
expect(operation_exception.message).not_to include('attempt 3')
|
146
|
+
end
|
147
|
+
|
148
|
+
it 'publishes one event' do
|
149
|
+
|
150
|
+
expect(events.length).to eq(1)
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
shared_examples_for 'failing retry on the same server' do
|
155
|
+
it 'is reported on the server of the second attempt' do
|
156
|
+
expect(operation_exception.message).to include(second_server.address.seed)
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
shared_examples_for 'failing retry on a different server' do
|
161
|
+
it 'is reported on the server of the second attempt' do
|
162
|
+
expect(operation_exception.message).not_to include(first_server.address.seed)
|
163
|
+
expect(operation_exception.message).to include(second_server.address.seed)
|
76
164
|
end
|
77
165
|
|
78
|
-
|
166
|
+
it 'marks servers used in both attempts unknown' do
|
167
|
+
operation_exception
|
168
|
+
|
169
|
+
expect(first_server).to be_unknown
|
170
|
+
|
171
|
+
expect(second_server).to be_unknown
|
172
|
+
end
|
79
173
|
|
80
|
-
|
81
|
-
|
174
|
+
it 'publishes events for the different server addresses' do
|
175
|
+
|
176
|
+
expect(events.length).to eq(2)
|
177
|
+
expect(events.first.address.seed).not_to eq(events.last.address.seed)
|
178
|
+
end
|
82
179
|
end
|
83
180
|
|
84
|
-
|
85
|
-
|
181
|
+
shared_examples_for 'modern retry' do
|
182
|
+
it 'indicates modern retry' do
|
183
|
+
expect(operation_exception.message).to include('modern retry')
|
184
|
+
expect(operation_exception.message).not_to include('legacy retry')
|
185
|
+
expect(operation_exception.message).not_to include('retries disabled')
|
186
|
+
end
|
187
|
+
end
|
86
188
|
|
87
|
-
|
88
|
-
|
189
|
+
shared_examples_for 'legacy retry' do
|
190
|
+
it 'indicates legacy retry' do
|
191
|
+
expect(operation_exception.message).to include('legacy retry')
|
192
|
+
expect(operation_exception.message).not_to include('modern retry')
|
193
|
+
expect(operation_exception.message).not_to include('retries disabled')
|
194
|
+
end
|
89
195
|
end
|
90
196
|
|
91
|
-
|
92
|
-
|
197
|
+
shared_examples_for 'disabled retry' do
|
198
|
+
it 'indicates retries are disabled' do
|
199
|
+
expect(operation_exception.message).to include('retries disabled')
|
200
|
+
expect(operation_exception.message).not_to include('legacy retry')
|
201
|
+
expect(operation_exception.message).not_to include('modern retry')
|
202
|
+
end
|
203
|
+
end
|
204
|
+
|
205
|
+
context 'when read is retried and retry fails' do
|
206
|
+
include_context 'read operation'
|
207
|
+
|
208
|
+
context 'modern read retries' do
|
209
|
+
require_wired_tiger_on_36
|
93
210
|
|
94
|
-
|
211
|
+
let(:client) do
|
212
|
+
subscribed_client.with(retry_reads: true)
|
213
|
+
end
|
95
214
|
|
96
|
-
|
215
|
+
it_behaves_like 'failing retry'
|
216
|
+
it_behaves_like 'modern retry'
|
217
|
+
end
|
218
|
+
|
219
|
+
context 'legacy read retries' do
|
220
|
+
let(:client) do
|
221
|
+
subscribed_client.with(retry_reads: false, read_retry_interval: 0)
|
222
|
+
end
|
223
|
+
|
224
|
+
it_behaves_like 'failing retry'
|
225
|
+
it_behaves_like 'legacy retry'
|
226
|
+
end
|
227
|
+
end
|
228
|
+
|
229
|
+
context 'when read retries are disabled' do
|
230
|
+
let(:client) do
|
231
|
+
subscribed_client.with(retry_reads: false, max_read_retries: 0)
|
232
|
+
end
|
233
|
+
|
234
|
+
include_context 'read operation'
|
235
|
+
|
236
|
+
it_behaves_like 'failing single attempt'
|
237
|
+
it_behaves_like 'disabled retry'
|
238
|
+
end
|
239
|
+
|
240
|
+
context 'when write is retried and retry fails' do
|
241
|
+
include_context 'write operation'
|
242
|
+
|
243
|
+
context 'modern write retries' do
|
244
|
+
require_wired_tiger_on_36
|
245
|
+
|
246
|
+
let(:client) do
|
247
|
+
subscribed_client.with(retry_writes: true)
|
248
|
+
end
|
249
|
+
|
250
|
+
it_behaves_like 'failing retry'
|
251
|
+
it_behaves_like 'modern retry'
|
252
|
+
end
|
253
|
+
|
254
|
+
context 'legacy write' do
|
255
|
+
let(:client) do
|
256
|
+
subscribed_client.with(retry_writes: false)
|
257
|
+
end
|
258
|
+
|
259
|
+
it_behaves_like 'failing retry'
|
260
|
+
it_behaves_like 'legacy retry'
|
261
|
+
end
|
97
262
|
end
|
98
263
|
end
|
99
264
|
end
|