mongo 2.10.5 → 2.11.0.rc0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (191) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +0 -0
  4. data/CONTRIBUTING.md +1 -1
  5. data/lib/mongo.rb +2 -0
  6. data/lib/mongo/address.rb +4 -0
  7. data/lib/mongo/address/validator.rb +99 -0
  8. data/lib/mongo/auth.rb +7 -2
  9. data/lib/mongo/auth/user.rb +1 -7
  10. data/lib/mongo/background_thread.rb +135 -0
  11. data/lib/mongo/bulk_write/transformable.rb +3 -3
  12. data/lib/mongo/client.rb +74 -16
  13. data/lib/mongo/cluster.rb +193 -41
  14. data/lib/mongo/cluster/periodic_executor.rb +31 -43
  15. data/lib/mongo/cluster/sdam_flow.rb +26 -3
  16. data/lib/mongo/cluster/srv_monitor.rb +127 -0
  17. data/lib/mongo/collection/view/readable.rb +3 -5
  18. data/lib/mongo/collection/view/writable.rb +3 -3
  19. data/lib/mongo/cursor/builder/get_more_command.rb +1 -4
  20. data/lib/mongo/cursor/builder/kill_cursors_command.rb +5 -23
  21. data/lib/mongo/cursor/builder/op_get_more.rb +2 -2
  22. data/lib/mongo/cursor/builder/op_kill_cursors.rb +5 -24
  23. data/lib/mongo/error.rb +1 -0
  24. data/lib/mongo/error/auth_error.rb +1 -1
  25. data/lib/mongo/error/connection_check_out_timeout.rb +7 -8
  26. data/lib/mongo/error/invalid_address.rb +24 -0
  27. data/lib/mongo/error/notable.rb +2 -2
  28. data/lib/mongo/error/operation_failure.rb +3 -3
  29. data/lib/mongo/error/pool_closed_error.rb +11 -4
  30. data/lib/mongo/event.rb +1 -1
  31. data/lib/mongo/grid/file.rb +0 -5
  32. data/lib/mongo/grid/file/chunk.rb +0 -2
  33. data/lib/mongo/grid/fs_bucket.rb +13 -15
  34. data/lib/mongo/grid/stream/write.rb +3 -9
  35. data/lib/mongo/loggable.rb +5 -1
  36. data/lib/mongo/monitoring.rb +1 -0
  37. data/lib/mongo/monitoring/event/cmap/connection_check_out_failed.rb +7 -0
  38. data/lib/mongo/monitoring/event/cmap/connection_checked_in.rb +11 -3
  39. data/lib/mongo/monitoring/event/cmap/connection_checked_out.rb +11 -3
  40. data/lib/mongo/monitoring/event/cmap/pool_closed.rb +11 -3
  41. data/lib/mongo/monitoring/event/cmap/pool_created.rb +12 -3
  42. data/lib/mongo/monitoring/unified_sdam_log_subscriber.rb +62 -0
  43. data/lib/mongo/operation/shared/executable.rb +5 -10
  44. data/lib/mongo/operation/shared/sessions_supported.rb +1 -5
  45. data/lib/mongo/protocol/get_more.rb +1 -2
  46. data/lib/mongo/protocol/kill_cursors.rb +13 -6
  47. data/lib/mongo/protocol/serializers.rb +4 -20
  48. data/lib/mongo/retryable.rb +9 -34
  49. data/lib/mongo/semaphore.rb +1 -1
  50. data/lib/mongo/server.rb +113 -42
  51. data/lib/mongo/server/connection.rb +12 -5
  52. data/lib/mongo/server/connection_pool.rb +250 -40
  53. data/lib/mongo/server/connection_pool/populator.rb +58 -0
  54. data/lib/mongo/server/description.rb +9 -2
  55. data/lib/mongo/server/monitor.rb +68 -93
  56. data/lib/mongo/server/monitor/connection.rb +2 -0
  57. data/lib/mongo/server_selector/selectable.rb +13 -5
  58. data/lib/mongo/session.rb +0 -13
  59. data/lib/mongo/srv.rb +17 -0
  60. data/lib/mongo/srv/monitor.rb +96 -0
  61. data/lib/mongo/srv/resolver.rb +130 -0
  62. data/lib/mongo/srv/result.rb +126 -0
  63. data/lib/mongo/srv/warning_result.rb +35 -0
  64. data/lib/mongo/uri.rb +45 -55
  65. data/lib/mongo/uri/srv_protocol.rb +89 -42
  66. data/lib/mongo/version.rb +1 -1
  67. data/mongo.gemspec +3 -4
  68. data/spec/README.md +6 -1
  69. data/spec/enterprise_auth/kerberos_spec.rb +7 -6
  70. data/spec/integration/change_stream_examples_spec.rb +0 -4
  71. data/spec/integration/client_construction_spec.rb +14 -2
  72. data/spec/integration/connect_single_rs_name_spec.rb +2 -2
  73. data/spec/integration/connection_pool_populator_spec.rb +296 -0
  74. data/spec/integration/connection_spec.rb +31 -22
  75. data/spec/integration/cursor_reaping_spec.rb +1 -2
  76. data/spec/integration/docs_examples_spec.rb +0 -4
  77. data/spec/integration/heartbeat_events_spec.rb +17 -15
  78. data/spec/integration/reconnect_spec.rb +144 -1
  79. data/spec/integration/retryable_writes_errors_spec.rb +0 -4
  80. data/spec/integration/retryable_writes_spec.rb +36 -36
  81. data/spec/integration/sdam_error_handling_spec.rb +31 -25
  82. data/spec/integration/sdam_events_spec.rb +2 -6
  83. data/spec/integration/server_monitor_spec.rb +28 -0
  84. data/spec/integration/server_selector_spec.rb +7 -5
  85. data/spec/integration/srv_monitoring_spec.rb +360 -0
  86. data/spec/integration/step_down_spec.rb +4 -6
  87. data/spec/lite_spec_helper.rb +22 -0
  88. data/spec/mongo/address/validator_spec.rb +51 -0
  89. data/spec/mongo/auth/cr_spec.rb +1 -29
  90. data/spec/mongo/auth/ldap_spec.rb +1 -29
  91. data/spec/mongo/auth/scram/conversation_spec.rb +0 -2
  92. data/spec/mongo/auth/scram/negotiation_spec.rb +1 -1
  93. data/spec/mongo/auth/scram_spec.rb +1 -29
  94. data/spec/mongo/auth/user/view_spec.rb +1 -36
  95. data/spec/mongo/auth/user_spec.rb +0 -12
  96. data/spec/mongo/auth/x509_spec.rb +1 -29
  97. data/spec/mongo/bulk_write_spec.rb +2 -2
  98. data/spec/mongo/client_construction_spec.rb +56 -15
  99. data/spec/mongo/client_spec.rb +31 -27
  100. data/spec/mongo/cluster/periodic_executor_spec.rb +16 -0
  101. data/spec/mongo/cluster/srv_monitor_spec.rb +214 -0
  102. data/spec/mongo/cluster/topology/replica_set_spec.rb +16 -11
  103. data/spec/mongo/cluster/topology/sharded_spec.rb +12 -9
  104. data/spec/mongo/cluster/topology/single_spec.rb +20 -11
  105. data/spec/mongo/cluster_spec.rb +45 -29
  106. data/spec/mongo/collection/view/map_reduce_spec.rb +14 -9
  107. data/spec/mongo/collection/view/readable_spec.rb +0 -16
  108. data/spec/mongo/collection_spec.rb +0 -44
  109. data/spec/mongo/cursor/builder/get_more_command_spec.rb +2 -4
  110. data/spec/mongo/cursor/builder/op_get_more_spec.rb +2 -4
  111. data/spec/mongo/cursor_spec.rb +27 -7
  112. data/spec/mongo/monitoring/event/cmap/connection_checked_in_spec.rb +10 -3
  113. data/spec/mongo/monitoring/event/cmap/connection_checked_out_spec.rb +10 -3
  114. data/spec/mongo/monitoring/event/cmap/pool_closed_spec.rb +10 -3
  115. data/spec/mongo/monitoring/event/cmap/pool_created_spec.rb +10 -3
  116. data/spec/mongo/operation/delete/op_msg_spec.rb +17 -8
  117. data/spec/mongo/operation/insert/op_msg_spec.rb +50 -35
  118. data/spec/mongo/operation/update/op_msg_spec.rb +14 -7
  119. data/spec/mongo/retryable_spec.rb +52 -31
  120. data/spec/mongo/server/app_metadata_spec.rb +0 -8
  121. data/spec/mongo/server/connection_auth_spec.rb +5 -2
  122. data/spec/mongo/server/connection_pool/populator_spec.rb +101 -0
  123. data/spec/mongo/server/connection_pool_spec.rb +256 -107
  124. data/spec/mongo/server/connection_spec.rb +22 -33
  125. data/spec/mongo/server/description_spec.rb +42 -4
  126. data/spec/mongo/server/monitor/connection_spec.rb +22 -11
  127. data/spec/mongo/server/monitor_spec.rb +66 -107
  128. data/spec/mongo/server_spec.rb +82 -60
  129. data/spec/mongo/session/session_pool_spec.rb +1 -5
  130. data/spec/mongo/session_spec.rb +0 -4
  131. data/spec/mongo/socket/ssl_spec.rb +2 -2
  132. data/spec/mongo/srv/monitor_spec.rb +211 -0
  133. data/spec/mongo/srv/result_spec.rb +54 -0
  134. data/spec/mongo/uri/srv_protocol_spec.rb +30 -15
  135. data/spec/mongo/uri_spec.rb +125 -4
  136. data/spec/spec_helper.rb +6 -0
  137. data/spec/spec_tests/auth_spec.rb +39 -0
  138. data/spec/spec_tests/cmap_spec.rb +55 -8
  139. data/spec/spec_tests/connection_string_spec.rb +6 -31
  140. data/spec/spec_tests/data/auth/connection-string.yml +297 -0
  141. data/spec/spec_tests/data/cmap/pool-checkout-error-closed.yml +4 -1
  142. data/spec/spec_tests/data/cmap/pool-create-with-options.yml +1 -0
  143. data/spec/spec_tests/data/command_monitoring/insertMany.yml +1 -1
  144. data/spec/spec_tests/data/connection_string/invalid-uris.yml +20 -0
  145. data/spec/spec_tests/data/connection_string/valid-auth.yml +16 -0
  146. data/spec/spec_tests/data/connection_string/valid-warnings.yml +26 -30
  147. data/spec/spec_tests/data/transactions/abort.yml +3 -3
  148. data/spec/spec_tests/data/transactions/error-labels.yml +3 -3
  149. data/spec/spec_tests/data/transactions_api/callback-retry.yml +3 -3
  150. data/spec/spec_tests/data/uri_options/auth-options.yml +1 -1
  151. data/spec/spec_tests/max_staleness_spec.rb +7 -2
  152. data/spec/spec_tests/retryable_reads_spec.rb +0 -31
  153. data/spec/spec_tests/sdam_monitoring_spec.rb +12 -12
  154. data/spec/spec_tests/sdam_spec.rb +4 -7
  155. data/spec/spec_tests/server_selection_spec.rb +6 -2
  156. data/spec/spec_tests/transactions_spec.rb +0 -2
  157. data/spec/spec_tests/uri_options_spec.rb +4 -2
  158. data/spec/stress/connection_pool_stress_spec.rb +203 -0
  159. data/spec/stress/connection_pool_timing_spec.rb +181 -0
  160. data/spec/support/auth.rb +113 -0
  161. data/spec/support/background_thread_registry.rb +63 -0
  162. data/spec/support/client_registry.rb +11 -2
  163. data/spec/support/cluster_config.rb +65 -46
  164. data/spec/support/cluster_tools.rb +2 -2
  165. data/spec/support/cmap.rb +13 -14
  166. data/spec/support/cmap/verifier.rb +4 -5
  167. data/spec/support/command_monitoring.rb +0 -5
  168. data/spec/support/common_shortcuts.rb +101 -1
  169. data/spec/support/constraints.rb +25 -0
  170. data/spec/support/dns.rb +13 -0
  171. data/spec/support/event_subscriber.rb +0 -7
  172. data/spec/support/json_ext_formatter.rb +5 -1
  173. data/spec/support/lite_constraints.rb +22 -6
  174. data/spec/support/local_resource_registry.rb +34 -0
  175. data/spec/support/sdam_monitoring.rb +115 -0
  176. data/spec/support/spec_config.rb +20 -6
  177. data/spec/support/spec_setup.rb +2 -2
  178. data/spec/support/transactions.rb +1 -1
  179. data/spec/support/transactions/test.rb +1 -1
  180. data/spec/support/utils.rb +1 -16
  181. metadata +685 -659
  182. metadata.gz.sig +0 -0
  183. data/lib/mongo/event/description_changed.rb +0 -52
  184. data/spec/integration/bson_symbol_spec.rb +0 -34
  185. data/spec/integration/crud_spec.rb +0 -45
  186. data/spec/integration/get_more_spec.rb +0 -32
  187. data/spec/integration/grid_fs_bucket_spec.rb +0 -48
  188. data/spec/integration/retryable_errors_spec.rb +0 -265
  189. data/spec/integration/size_limit_spec.rb~12e1e9c4f... RUBY-2242 Fix zlib compression (#2021) +0 -98
  190. data/spec/mongo/cursor/builder/op_kill_cursors_spec.rb +0 -56
  191. data/spec/runners/sdam/verifier.rb +0 -88
@@ -5,9 +5,7 @@ describe Mongo::Cursor::Builder::GetMoreCommand do
5
5
  describe '#specification' do
6
6
 
7
7
  let(:reply) do
8
- Mongo::Protocol::Reply.allocate.tap do |reply|
9
- allow(reply).to receive(:cursor_id).and_return(8000)
10
- end
8
+ Mongo::Protocol::Reply.allocate
11
9
  end
12
10
 
13
11
  let(:result) do
@@ -56,7 +54,7 @@ describe Mongo::Cursor::Builder::GetMoreCommand do
56
54
  end
57
55
 
58
56
  it 'includes getMore with cursor id' do
59
- expect(selector[:getMore]).to eq(BSON::Int64.new(8000))
57
+ expect(selector[:getMore]).to eq(cursor.id)
60
58
  end
61
59
 
62
60
  it 'includes the collection name' do
@@ -5,9 +5,7 @@ describe Mongo::Cursor::Builder::OpGetMore do
5
5
  describe '#specification' do
6
6
 
7
7
  let(:reply) do
8
- Mongo::Protocol::Reply.allocate.tap do |reply|
9
- allow(reply).to receive(:cursor_id).and_return(8000)
10
- end
8
+ Mongo::Protocol::Reply.allocate
11
9
  end
12
10
 
13
11
  let(:result) do
@@ -40,7 +38,7 @@ describe Mongo::Cursor::Builder::OpGetMore do
40
38
  end
41
39
 
42
40
  it 'includes the cursor id' do
43
- expect(specification[:cursor_id]).to eq(BSON::Int64.new(8000))
41
+ expect(specification[:cursor_id]).to eq(cursor.id)
44
42
  end
45
43
 
46
44
  it 'includes the database name' do
@@ -27,10 +27,23 @@ describe Mongo::Cursor do
27
27
  authorized_collection.insert_many(documents)
28
28
  end
29
29
 
30
- context 'cursor exhausted by initial result' do
30
+ shared_context 'with initialized pool' do
31
31
  before do
32
32
  ClientRegistry.instance.close_all_clients
33
+
34
+ # These tests really like creating pools (and thus scheduling
35
+ # the pools' finalizers) when querying collections.
36
+ # Deal with this by pre-creating pools for all known servers.
37
+ cluster = authorized_collection.client.cluster
38
+ cluster.next_primary
39
+ cluster.servers_list.each do |server|
40
+ server.pool
41
+ end
33
42
  end
43
+ end
44
+
45
+ context 'cursor exhausted by initial result' do
46
+ include_context 'with initialized pool'
34
47
 
35
48
  let(:view) do
36
49
  Mongo::Collection::View.new(authorized_collection)
@@ -47,15 +60,19 @@ describe Mongo::Cursor do
47
60
  end
48
61
 
49
62
  context 'cursor not exhausted by initial result' do
50
- clean_slate
63
+ include_context 'with initialized pool'
51
64
 
52
65
  let(:view) do
53
66
  Mongo::Collection::View.new(authorized_collection, {}, batch_size: 2)
54
67
  end
55
68
 
56
69
  it 'schedules the finalizer' do
57
- expect(ObjectSpace).to receive(:define_finalizer)
58
- cursor
70
+ # Due to https://jira.mongodb.org/browse/RUBY-1772, restrict
71
+ # the scope of the assertion
72
+ RSpec::Mocks.with_temporary_scope do
73
+ expect(ObjectSpace).to receive(:define_finalizer)
74
+ cursor
75
+ end
59
76
  end
60
77
  end
61
78
  end
@@ -301,7 +318,7 @@ describe Mongo::Cursor do
301
318
  Mongo::Collection::View.new(
302
319
  authorized_collection,
303
320
  {},
304
- :batch_size => 2,
321
+ :batch_size => 2
305
322
  )
306
323
  end
307
324
 
@@ -312,12 +329,15 @@ describe Mongo::Cursor do
312
329
 
313
330
  it 'schedules a kill cursors op' do
314
331
  cluster.instance_variable_get(:@periodic_executor).flush
315
- expect do
332
+ expect {
316
333
  cursor.to_a
317
- end.to raise_exception(Mongo::Error::OperationFailure, /[cC]ursor.*not found/)
334
+ }.to raise_exception(Mongo::Error::OperationFailure, /[cC]ursor.*not found/)
318
335
  end
319
336
 
320
337
  context 'when the cursor is unregistered before the kill cursors operations are executed' do
338
+ # Sometimes JRuby yields 4 documents even though we are allowing
339
+ # repeated cursor iteration below
340
+ fails_on_jruby
321
341
 
322
342
  it 'does not send a kill cursors operation for the unregistered cursor' do
323
343
  # We need to verify that the cursor was able to retrieve more documents
@@ -1,4 +1,4 @@
1
- require 'lite_spec_helper'
1
+ require 'spec_helper'
2
2
 
3
3
  describe Mongo::Monitoring::Event::Cmap::ConnectionCheckedIn do
4
4
 
@@ -12,12 +12,19 @@ describe Mongo::Monitoring::Event::Cmap::ConnectionCheckedIn do
12
12
  1
13
13
  end
14
14
 
15
+ declare_topology_double
16
+
17
+ let(:pool) do
18
+ server = make_server(:primary)
19
+ Mongo::Server::ConnectionPool.new(server)
20
+ end
21
+
15
22
  let(:event) do
16
- described_class.new(address, id)
23
+ described_class.new(address, id, pool)
17
24
  end
18
25
 
19
26
  it 'renders correctly' do
20
- expect(event.summary).to eq('#<ConnectionCheckedIn address=127.0.0.1:27017 connection_id=1>')
27
+ expect(event.summary).to eq("#<ConnectionCheckedIn address=127.0.0.1:27017 connection_id=1 pool=0x#{pool.object_id}>")
21
28
  end
22
29
  end
23
30
  end
@@ -1,4 +1,4 @@
1
- require 'lite_spec_helper'
1
+ require 'spec_helper'
2
2
 
3
3
  describe Mongo::Monitoring::Event::Cmap::ConnectionCheckedOut do
4
4
 
@@ -12,12 +12,19 @@ describe Mongo::Monitoring::Event::Cmap::ConnectionCheckedOut do
12
12
  1
13
13
  end
14
14
 
15
+ declare_topology_double
16
+
17
+ let(:pool) do
18
+ server = make_server(:primary)
19
+ Mongo::Server::ConnectionPool.new(server)
20
+ end
21
+
15
22
  let(:event) do
16
- described_class.new(address, id)
23
+ described_class.new(address, id, pool)
17
24
  end
18
25
 
19
26
  it 'renders correctly' do
20
- expect(event.summary).to eq('#<ConnectionCheckedOut address=127.0.0.1:27017 connection_id=1>')
27
+ expect(event.summary).to eq("#<ConnectionCheckedOut address=127.0.0.1:27017 connection_id=1 pool=0x#{pool.object_id}>")
21
28
  end
22
29
  end
23
30
  end
@@ -1,4 +1,4 @@
1
- require 'lite_spec_helper'
1
+ require 'spec_helper'
2
2
 
3
3
  describe Mongo::Monitoring::Event::Cmap::PoolClosed do
4
4
 
@@ -8,12 +8,19 @@ describe Mongo::Monitoring::Event::Cmap::PoolClosed do
8
8
  Mongo::Address.new('127.0.0.1:27017')
9
9
  end
10
10
 
11
+ declare_topology_double
12
+
13
+ let(:pool) do
14
+ server = make_server(:primary)
15
+ Mongo::Server::ConnectionPool.new(server)
16
+ end
17
+
11
18
  let(:event) do
12
- described_class.new(address)
19
+ described_class.new(address, pool)
13
20
  end
14
21
 
15
22
  it 'renders correctly' do
16
- expect(event.summary).to eq('#<PoolClosed address=127.0.0.1:27017>')
23
+ expect(event.summary).to eq("#<PoolClosed address=127.0.0.1:27017 pool=0x#{pool.object_id}>")
17
24
  end
18
25
  end
19
26
  end
@@ -1,4 +1,4 @@
1
- require 'lite_spec_helper'
1
+ require 'spec_helper'
2
2
 
3
3
  describe Mongo::Monitoring::Event::Cmap::PoolCreated do
4
4
 
@@ -15,12 +15,19 @@ describe Mongo::Monitoring::Event::Cmap::PoolCreated do
15
15
  }
16
16
  end
17
17
 
18
+ declare_topology_double
19
+
20
+ let(:pool) do
21
+ server = make_server(:primary)
22
+ Mongo::Server::ConnectionPool.new(server)
23
+ end
24
+
18
25
  let(:event) do
19
- described_class.new(address, options)
26
+ described_class.new(address, options, pool)
20
27
  end
21
28
 
22
29
  it 'renders correctly' do
23
- expect(event.summary).to eq('#<PoolCreated address=127.0.0.1:27017 options={:wait_queue_timeout=>3, :min_pool_size=>5}>')
30
+ expect(event.summary).to eq("#<PoolCreated address=127.0.0.1:27017 options={:wait_queue_timeout=>3, :min_pool_size=>5} pool=0x#{pool.object_id}>")
24
31
  end
25
32
  end
26
33
  end
@@ -143,6 +143,8 @@ describe Mongo::Operation::Delete::OpMsg do
143
143
  end
144
144
 
145
145
  context 'when an implicit session is created and the topology is then updated and the server does not support sessions' do
146
+ # Mocks on features are incompatible with linting
147
+ skip_if_linting
146
148
 
147
149
  let(:expected_global_args) do
148
150
  global_args.dup.tap do |args|
@@ -153,15 +155,20 @@ describe Mongo::Operation::Delete::OpMsg do
153
155
  before do
154
156
  session.instance_variable_set(:@options, { implicit: true })
155
157
  # Topology is standalone, hence there is exactly one server
156
- authorized_client.cluster.servers.first.monitor.stop!(true)
157
- allow(authorized_primary.features).to receive(:sessions_enabled?).and_return(false)
158
+ authorized_primary.monitor.stop!
158
159
  end
159
160
 
160
161
  it 'creates the correct OP_MSG message' do
161
- authorized_client.command(ping:1)
162
- expect(expected_global_args[:session]).to be nil
163
- expect(Mongo::Protocol::Msg).to receive(:new).with([], {}, expected_global_args, expected_payload_1)
164
- op.send(:message, authorized_primary)
162
+ RSpec::Mocks.with_temporary_scope do
163
+ # Override description as it gets replaced on every connection
164
+ description = authorized_primary.description
165
+ allow(authorized_primary).to receive(:description).and_return(description)
166
+ allow(description.features).to receive(:sessions_enabled?).and_return(false)
167
+
168
+ expect(expected_global_args[:session]).to be nil
169
+ expect(Mongo::Protocol::Msg).to receive(:new).with([], {}, expected_global_args, expected_payload_1)
170
+ op.send(:message, authorized_primary)
171
+ end
165
172
  end
166
173
  end
167
174
  end
@@ -232,8 +239,10 @@ describe Mongo::Operation::Delete::OpMsg do
232
239
 
233
240
  it 'does not send a session id in the command' do
234
241
  authorized_client.command(ping:1)
235
- expect(Mongo::Protocol::Msg).to receive(:new).with([:more_to_come], {}, expected_global_args, expected_payload_1)
236
- op.send(:message, authorized_primary)
242
+ RSpec::Mocks.with_temporary_scope do
243
+ expect(Mongo::Protocol::Msg).to receive(:new).with([:more_to_come], {}, expected_global_args, expected_payload_1)
244
+ op.send(:message, authorized_primary)
245
+ end
237
246
  end
238
247
  end
239
248
  end
@@ -128,11 +128,13 @@ describe Mongo::Operation::Insert::OpMsg do
128
128
 
129
129
  it 'creates the correct OP_MSG message' do
130
130
  authorized_client.command(ping:1)
131
- expect(Mongo::Protocol::Msg).to receive(:new).with([],
132
- { validating_keys: true },
133
- expected_global_args,
134
- expected_payload_1)
135
- op.send(:message, authorized_primary)
131
+ RSpec::Mocks.with_temporary_scope do
132
+ expect(Mongo::Protocol::Msg).to receive(:new).with([],
133
+ { validating_keys: true },
134
+ expected_global_args,
135
+ expected_payload_1)
136
+ op.send(:message, authorized_primary)
137
+ end
136
138
  end
137
139
  end
138
140
 
@@ -145,12 +147,14 @@ describe Mongo::Operation::Insert::OpMsg do
145
147
  end
146
148
 
147
149
  it 'creates the correct OP_MSG message' do
148
- authorized_client.command(ping:1)
149
- expect(Mongo::Protocol::Msg).to receive(:new).with([],
150
- { validating_keys: true },
151
- expected_global_args,
152
- expected_payload_1)
153
- op.send(:message, authorized_primary)
150
+ RSpec::Mocks.with_temporary_scope do
151
+ authorized_client.command(ping:1)
152
+ expect(Mongo::Protocol::Msg).to receive(:new).with([],
153
+ { validating_keys: true },
154
+ expected_global_args,
155
+ expected_payload_1)
156
+ op.send(:message, authorized_primary)
157
+ end
154
158
  end
155
159
 
156
160
  context 'when an implicit session is created and the topology is then updated and the server does not support sessions' do
@@ -164,18 +168,23 @@ describe Mongo::Operation::Insert::OpMsg do
164
168
  before do
165
169
  session.instance_variable_set(:@options, { implicit: true })
166
170
  # Topology is standalone, hence there is exactly one server
167
- authorized_client.cluster.servers.first.monitor.stop!(true)
168
- expect(authorized_primary.features).to receive(:sessions_enabled?).at_least(:once).and_return(false)
171
+ authorized_primary.monitor.stop!
169
172
  end
170
173
 
171
174
  it 'creates the correct OP_MSG message' do
172
- authorized_client.command(ping:1)
173
- expect(expected_global_args).not_to have_key(:lsid)
174
- expect(Mongo::Protocol::Msg).to receive(:new).with([],
175
- { validating_keys: true },
176
- expected_global_args,
177
- expected_payload_1)
178
- op.send(:message, authorized_primary)
175
+ RSpec::Mocks.with_temporary_scope do
176
+ # Override description as it gets replaced on every connection
177
+ description = authorized_primary.description
178
+ allow(authorized_primary).to receive(:description).and_return(description)
179
+ allow(description.features).to receive(:sessions_enabled?).and_return(false)
180
+
181
+ expect(expected_global_args).not_to have_key(:lsid)
182
+ expect(Mongo::Protocol::Msg).to receive(:new).with([],
183
+ { validating_keys: true },
184
+ expected_global_args,
185
+ expected_payload_1)
186
+ op.send(:message, authorized_primary)
187
+ end
179
188
  end
180
189
  end
181
190
  end
@@ -206,11 +215,13 @@ describe Mongo::Operation::Insert::OpMsg do
206
215
 
207
216
  it 'does not send a session id in the command' do
208
217
  authorized_client.command(ping:1)
209
- expect(Mongo::Protocol::Msg).to receive(:new).with([:more_to_come],
210
- { validating_keys: true },
211
- expected_global_args,
212
- expected_payload_1)
213
- op.send(:message, authorized_primary)
218
+ RSpec::Mocks.with_temporary_scope do
219
+ expect(Mongo::Protocol::Msg).to receive(:new).with([:more_to_come],
220
+ { validating_keys: true },
221
+ expected_global_args,
222
+ expected_payload_1)
223
+ op.send(:message, authorized_primary)
224
+ end
214
225
  end
215
226
  end
216
227
 
@@ -226,11 +237,13 @@ describe Mongo::Operation::Insert::OpMsg do
226
237
 
227
238
  it 'creates the correct OP_MSG message' do
228
239
  authorized_client.command(ping:1)
229
- expect(Mongo::Protocol::Msg).to receive(:new).with([:more_to_come],
230
- { validating_keys: true },
231
- expected_global_args,
232
- expected_payload_1)
233
- op.send(:message, authorized_primary)
240
+ RSpec::Mocks.with_temporary_scope do
241
+ expect(Mongo::Protocol::Msg).to receive(:new).with([:more_to_come],
242
+ { validating_keys: true },
243
+ expected_global_args,
244
+ expected_payload_1)
245
+ op.send(:message, authorized_primary)
246
+ end
234
247
  end
235
248
  end
236
249
  end
@@ -252,11 +265,13 @@ describe Mongo::Operation::Insert::OpMsg do
252
265
 
253
266
  it 'does not send a session id in the command' do
254
267
  authorized_client.command(ping:1)
255
- expect(Mongo::Protocol::Msg).to receive(:new).with([:more_to_come],
256
- { validating_keys: true },
257
- expected_global_args,
258
- expected_payload_1)
259
- op.send(:message, authorized_primary)
268
+ RSpec::Mocks.with_temporary_scope do
269
+ expect(Mongo::Protocol::Msg).to receive(:new).with([:more_to_come],
270
+ { validating_keys: true },
271
+ expected_global_args,
272
+ expected_payload_1)
273
+ op.send(:message, authorized_primary)
274
+ end
260
275
  end
261
276
  end
262
277
  end
@@ -160,14 +160,19 @@ describe Mongo::Operation::Update::OpMsg do
160
160
  before do
161
161
  session.instance_variable_set(:@options, { implicit: true })
162
162
  # Topology is standalone, hence there is exactly one server
163
- authorized_client.cluster.servers.first.monitor.stop!(true)
164
- allow(authorized_primary.features).to receive(:sessions_enabled?).and_return(false)
163
+ authorized_primary.monitor.stop!
165
164
  end
166
165
 
167
166
  it 'creates the correct OP_MSG message' do
168
- authorized_client.command(ping:1)
169
- expect(Mongo::Protocol::Msg).to receive(:new).with([], {}, expected_global_args, expected_payload_1)
170
- op.send(:message, authorized_primary)
167
+ RSpec::Mocks.with_temporary_scope do
168
+ # Override description as it gets replaced on every connection
169
+ description = authorized_primary.description
170
+ allow(authorized_primary).to receive(:description).and_return(description)
171
+ allow(description.features).to receive(:sessions_enabled?).and_return(false)
172
+
173
+ expect(Mongo::Protocol::Msg).to receive(:new).with([], {}, expected_global_args, expected_payload_1)
174
+ op.send(:message, authorized_primary)
175
+ end
171
176
  end
172
177
  end
173
178
  end
@@ -238,8 +243,10 @@ describe Mongo::Operation::Update::OpMsg do
238
243
 
239
244
  it 'does not send a session id in the command' do
240
245
  authorized_client.command(ping:1)
241
- expect(Mongo::Protocol::Msg).to receive(:new).with([:more_to_come], {}, expected_global_args, expected_payload_1)
242
- op.send(:message, authorized_primary)
246
+ RSpec::Mocks.with_temporary_scope do
247
+ expect(Mongo::Protocol::Msg).to receive(:new).with([:more_to_come], {}, expected_global_args, expected_payload_1)
248
+ op.send(:message, authorized_primary)
249
+ end
243
250
  end
244
251
  end
245
252
  end
@@ -175,62 +175,83 @@ describe Mongo::Retryable do
175
175
 
176
176
  context 'when an operation failure occurs' do
177
177
 
178
- context 'when the operation failure is not retryable' do
179
-
180
- let(:error) do
181
- Mongo::Error::OperationFailure.new('not authorized')
182
- end
178
+ context 'when the cluster is not a mongos' do
183
179
 
184
180
  before do
185
- expect(operation).to receive(:execute).and_raise(error).ordered
181
+ expect(operation).to receive(:execute).and_raise(Mongo::Error::OperationFailure).ordered
182
+ expect(cluster).to receive(:sharded?).and_return(false)
186
183
  end
187
184
 
188
- it 'raises the exception' do
185
+ it 'raises an exception' do
189
186
  expect {
190
187
  read_operation
191
188
  }.to raise_error(Mongo::Error::OperationFailure)
192
189
  end
193
190
  end
194
191
 
195
- context 'when the operation failure is retryable' do
192
+ context 'when the cluster is a mongos' do
196
193
 
197
- let(:error) do
198
- Mongo::Error::OperationFailure.new('not master')
199
- end
194
+ context 'when the operation failure is not retryable' do
200
195
 
201
- context 'when the retry succeeds' do
196
+ let(:error) do
197
+ Mongo::Error::OperationFailure.new('not authorized')
198
+ end
202
199
 
203
200
  before do
204
- expect(retryable).to receive(:select_server).ordered
205
201
  expect(operation).to receive(:execute).and_raise(error).ordered
206
- expect(client).to receive(:read_retry_interval).and_return(0.1).ordered
207
- expect(retryable).to receive(:select_server).ordered
208
- expect(operation).to receive(:execute).and_return(true).ordered
202
+ expect(cluster).to receive(:sharded?).and_return(true)
209
203
  end
210
204
 
211
- it 'returns the result' do
212
- expect(read_operation).to be true
205
+ it 'raises the exception' do
206
+ expect {
207
+ read_operation
208
+ }.to raise_error(Mongo::Error::OperationFailure)
213
209
  end
214
210
  end
215
211
 
216
- context 'when the retry fails once and then succeeds' do
217
- let(:max_read_retries) { 2 }
212
+ context 'when the operation failure is retryable' do
218
213
 
219
- before do
220
- expect(retryable).to receive(:select_server).ordered
221
- expect(operation).to receive(:execute).and_raise(error).ordered
214
+ let(:error) do
215
+ Mongo::Error::OperationFailure.new('not master')
216
+ end
222
217
 
223
- expect(client).to receive(:read_retry_interval).and_return(0.1).ordered
224
- expect(retryable).to receive(:select_server).ordered
225
- expect(operation).to receive(:execute).and_raise(error).ordered
218
+ context 'when the retry succeeds' do
219
+
220
+ before do
221
+ expect(retryable).to receive(:select_server).ordered
222
+ expect(operation).to receive(:execute).and_raise(error).ordered
223
+ expect(cluster).to receive(:sharded?).and_return(true)
224
+ expect(client).to receive(:read_retry_interval).and_return(0.1).ordered
225
+ expect(retryable).to receive(:select_server).ordered
226
+ expect(operation).to receive(:execute).and_return(true).ordered
227
+ end
226
228
 
227
- expect(client).to receive(:read_retry_interval).and_return(0.1).ordered
228
- expect(retryable).to receive(:select_server).ordered
229
- expect(operation).to receive(:execute).and_return(true).ordered
229
+ it 'returns the result' do
230
+ expect(read_operation).to be true
231
+ end
230
232
  end
231
233
 
232
- it 'returns the result' do
233
- expect(read_operation).to be true
234
+ context 'when the retry fails once and then succeeds' do
235
+ let(:max_read_retries) { 2 }
236
+
237
+ before do
238
+ expect(retryable).to receive(:select_server).ordered
239
+ expect(operation).to receive(:execute).and_raise(error).ordered
240
+
241
+ expect(cluster).to receive(:sharded?).and_return(true)
242
+ expect(client).to receive(:read_retry_interval).and_return(0.1).ordered
243
+ expect(retryable).to receive(:select_server).ordered
244
+ expect(operation).to receive(:execute).and_raise(error).ordered
245
+
246
+ expect(cluster).to receive(:sharded?).and_return(true)
247
+ expect(client).to receive(:read_retry_interval).and_return(0.1).ordered
248
+ expect(retryable).to receive(:select_server).ordered
249
+ expect(operation).to receive(:execute).and_return(true).ordered
250
+ end
251
+
252
+ it 'returns the result' do
253
+ expect(read_operation).to be true
254
+ end
234
255
  end
235
256
  end
236
257
  end