mongo 2.13.0.beta1 → 2.13.0.rc1

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.
Files changed (170) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +1 -5
  4. data/Rakefile +15 -9
  5. data/lib/mongo.rb +4 -2
  6. data/lib/mongo/auth/aws/request.rb +4 -2
  7. data/lib/mongo/bulk_write.rb +1 -0
  8. data/lib/mongo/client.rb +143 -21
  9. data/lib/mongo/cluster.rb +53 -17
  10. data/lib/mongo/cluster/sdam_flow.rb +13 -10
  11. data/lib/mongo/cluster/topology/replica_set_no_primary.rb +3 -2
  12. data/lib/mongo/cluster/topology/sharded.rb +1 -1
  13. data/lib/mongo/cluster/topology/single.rb +1 -1
  14. data/lib/mongo/collection.rb +17 -13
  15. data/lib/mongo/collection/view/readable.rb +3 -1
  16. data/lib/mongo/collection/view/writable.rb +41 -5
  17. data/lib/mongo/database.rb +31 -4
  18. data/lib/mongo/database/view.rb +19 -4
  19. data/lib/mongo/distinguishing_semaphore.rb +55 -0
  20. data/lib/mongo/error.rb +1 -0
  21. data/lib/mongo/error/invalid_session.rb +2 -1
  22. data/lib/mongo/error/operation_failure.rb +6 -0
  23. data/lib/mongo/error/sessions_not_supported.rb +35 -0
  24. data/lib/mongo/event/base.rb +6 -0
  25. data/lib/mongo/grid/file.rb +5 -0
  26. data/lib/mongo/grid/file/chunk.rb +2 -0
  27. data/lib/mongo/grid/fs_bucket.rb +15 -13
  28. data/lib/mongo/grid/stream/write.rb +9 -3
  29. data/lib/mongo/monitoring.rb +38 -0
  30. data/lib/mongo/monitoring/command_log_subscriber.rb +10 -2
  31. data/lib/mongo/monitoring/event/command_failed.rb +11 -0
  32. data/lib/mongo/monitoring/event/command_started.rb +37 -2
  33. data/lib/mongo/monitoring/event/command_succeeded.rb +11 -0
  34. data/lib/mongo/monitoring/event/server_closed.rb +1 -1
  35. data/lib/mongo/monitoring/event/server_description_changed.rb +27 -4
  36. data/lib/mongo/monitoring/event/server_heartbeat_failed.rb +9 -2
  37. data/lib/mongo/monitoring/event/server_heartbeat_started.rb +9 -2
  38. data/lib/mongo/monitoring/event/server_heartbeat_succeeded.rb +9 -2
  39. data/lib/mongo/monitoring/event/server_opening.rb +1 -1
  40. data/lib/mongo/monitoring/event/topology_changed.rb +1 -1
  41. data/lib/mongo/monitoring/event/topology_closed.rb +1 -1
  42. data/lib/mongo/monitoring/event/topology_opening.rb +1 -1
  43. data/lib/mongo/monitoring/publishable.rb +6 -3
  44. data/lib/mongo/monitoring/server_description_changed_log_subscriber.rb +9 -1
  45. data/lib/mongo/monitoring/topology_changed_log_subscriber.rb +1 -1
  46. data/lib/mongo/protocol/message.rb +36 -8
  47. data/lib/mongo/protocol/msg.rb +14 -0
  48. data/lib/mongo/protocol/serializers.rb +5 -2
  49. data/lib/mongo/server.rb +10 -3
  50. data/lib/mongo/server/connection.rb +4 -4
  51. data/lib/mongo/server/connection_base.rb +3 -1
  52. data/lib/mongo/server/description.rb +5 -0
  53. data/lib/mongo/server/monitor.rb +76 -44
  54. data/lib/mongo/server/monitor/connection.rb +55 -7
  55. data/lib/mongo/server/pending_connection.rb +14 -4
  56. data/lib/mongo/server/push_monitor.rb +173 -0
  57. data/{spec/runners/transactions/context.rb → lib/mongo/server/push_monitor/connection.rb} +9 -14
  58. data/lib/mongo/server_selector.rb +0 -1
  59. data/lib/mongo/server_selector/base.rb +579 -1
  60. data/lib/mongo/server_selector/nearest.rb +1 -6
  61. data/lib/mongo/server_selector/primary.rb +1 -6
  62. data/lib/mongo/server_selector/primary_preferred.rb +7 -10
  63. data/lib/mongo/server_selector/secondary.rb +1 -6
  64. data/lib/mongo/server_selector/secondary_preferred.rb +1 -7
  65. data/lib/mongo/session.rb +2 -0
  66. data/lib/mongo/socket.rb +20 -8
  67. data/lib/mongo/socket/ssl.rb +1 -1
  68. data/lib/mongo/socket/tcp.rb +1 -1
  69. data/lib/mongo/topology_version.rb +9 -0
  70. data/lib/mongo/utils.rb +62 -0
  71. data/lib/mongo/version.rb +1 -1
  72. data/spec/README.aws-auth.md +2 -2
  73. data/spec/integration/awaited_ismaster_spec.rb +28 -0
  74. data/spec/integration/change_stream_examples_spec.rb +6 -2
  75. data/spec/integration/check_clean_slate_spec.rb +16 -0
  76. data/spec/integration/client_construction_spec.rb +1 -0
  77. data/spec/integration/connect_single_rs_name_spec.rb +5 -2
  78. data/spec/integration/connection_spec.rb +7 -4
  79. data/spec/integration/crud_spec.rb +4 -4
  80. data/spec/integration/docs_examples_spec.rb +6 -0
  81. data/spec/integration/grid_fs_bucket_spec.rb +48 -0
  82. data/spec/integration/heartbeat_events_spec.rb +4 -23
  83. data/spec/integration/read_concern_spec.rb +1 -1
  84. data/spec/integration/retryable_errors_spec.rb +1 -1
  85. data/spec/integration/retryable_writes/shared/performs_legacy_retries.rb +2 -2
  86. data/spec/integration/retryable_writes/shared/performs_modern_retries.rb +3 -3
  87. data/spec/integration/retryable_writes/shared/performs_no_retries.rb +2 -2
  88. data/spec/integration/sdam_error_handling_spec.rb +37 -15
  89. data/spec/integration/sdam_events_spec.rb +77 -6
  90. data/spec/integration/sdam_prose_spec.rb +64 -0
  91. data/spec/integration/server_monitor_spec.rb +25 -1
  92. data/spec/integration/size_limit_spec.rb +7 -3
  93. data/spec/integration/size_limit_spec.rb~12e1e9c4f... RUBY-2242 Fix zlib compression (#2021) +98 -0
  94. data/spec/integration/ssl_uri_options_spec.rb +2 -2
  95. data/spec/integration/zlib_compression_spec.rb +25 -0
  96. data/spec/lite_spec_helper.rb +12 -5
  97. data/spec/mongo/auth/aws/request_spec.rb +76 -0
  98. data/spec/mongo/auth/scram_spec.rb +1 -1
  99. data/spec/mongo/client_construction_spec.rb +207 -0
  100. data/spec/mongo/client_spec.rb +38 -3
  101. data/spec/mongo/cluster/topology/replica_set_spec.rb +52 -9
  102. data/spec/mongo/cluster/topology/single_spec.rb +4 -2
  103. data/spec/mongo/cluster_spec.rb +34 -35
  104. data/spec/mongo/collection/view/change_stream_resume_spec.rb +6 -6
  105. data/spec/mongo/collection_spec.rb +500 -0
  106. data/spec/mongo/database_spec.rb +245 -8
  107. data/spec/mongo/distinguishing_semaphore_spec.rb +63 -0
  108. data/spec/mongo/error/operation_failure_spec.rb +40 -0
  109. data/spec/mongo/index/view_spec.rb +2 -2
  110. data/spec/mongo/monitoring/event/server_description_changed_spec.rb +1 -4
  111. data/spec/mongo/protocol/msg_spec.rb +10 -0
  112. data/spec/mongo/semaphore_spec.rb +51 -0
  113. data/spec/mongo/server/connection_auth_spec.rb +2 -2
  114. data/spec/mongo/server_selector/nearest_spec.rb +23 -23
  115. data/spec/mongo/server_selector/primary_preferred_spec.rb +26 -26
  116. data/spec/mongo/server_selector/primary_spec.rb +9 -9
  117. data/spec/mongo/server_selector/secondary_preferred_spec.rb +22 -22
  118. data/spec/mongo/server_selector/secondary_spec.rb +18 -18
  119. data/spec/mongo/server_selector_spec.rb +4 -4
  120. data/spec/mongo/session_spec.rb +35 -0
  121. data/spec/runners/change_streams/test.rb +2 -2
  122. data/spec/runners/cmap.rb +1 -1
  123. data/spec/runners/command_monitoring.rb +3 -34
  124. data/spec/runners/crud/context.rb +9 -5
  125. data/spec/runners/crud/operation.rb +59 -27
  126. data/spec/runners/crud/spec.rb +0 -8
  127. data/spec/runners/crud/test.rb +1 -1
  128. data/spec/runners/sdam.rb +2 -2
  129. data/spec/runners/server_selection.rb +242 -28
  130. data/spec/runners/transactions.rb +12 -12
  131. data/spec/runners/transactions/operation.rb +151 -25
  132. data/spec/runners/transactions/test.rb +60 -16
  133. data/spec/spec_tests/command_monitoring_spec.rb +22 -12
  134. data/spec/spec_tests/crud_spec.rb +1 -1
  135. data/spec/spec_tests/data/change_streams/change-streams-errors.yml +4 -8
  136. data/spec/spec_tests/data/change_streams/change-streams-resume-whitelist.yml +66 -0
  137. data/spec/spec_tests/data/max_staleness/ReplicaSetNoPrimary/MaxStalenessTooSmall.yml +15 -0
  138. data/spec/spec_tests/data/max_staleness/ReplicaSetNoPrimary/NoKnownServers.yml +4 -3
  139. data/spec/spec_tests/data/max_staleness/Unknown/SmallMaxStaleness.yml +1 -0
  140. data/spec/spec_tests/data/sdam_integration/cancel-server-check.yml +96 -0
  141. data/spec/spec_tests/data/sdam_integration/connectTimeoutMS.yml +88 -0
  142. data/spec/spec_tests/data/sdam_integration/find-network-error.yml +83 -0
  143. data/spec/spec_tests/data/sdam_integration/find-shutdown-error.yml +116 -0
  144. data/spec/spec_tests/data/sdam_integration/insert-network-error.yml +86 -0
  145. data/spec/spec_tests/data/sdam_integration/insert-shutdown-error.yml +115 -0
  146. data/spec/spec_tests/data/sdam_integration/isMaster-command-error.yml +168 -0
  147. data/spec/spec_tests/data/sdam_integration/isMaster-network-error.yml +162 -0
  148. data/spec/spec_tests/data/sdam_integration/isMaster-timeout.yml +229 -0
  149. data/spec/spec_tests/data/sdam_integration/rediscover-quickly-after-step-down.yml +87 -0
  150. data/spec/spec_tests/max_staleness_spec.rb +4 -142
  151. data/spec/spec_tests/retryable_reads_spec.rb +2 -2
  152. data/spec/spec_tests/sdam_integration_spec.rb +13 -0
  153. data/spec/spec_tests/sdam_monitoring_spec.rb +1 -2
  154. data/spec/spec_tests/server_selection_spec.rb +4 -116
  155. data/spec/stress/cleanup_spec.rb +17 -2
  156. data/spec/stress/connection_pool_stress_spec.rb +10 -8
  157. data/spec/support/child_process_helper.rb +78 -0
  158. data/spec/support/client_registry.rb +1 -0
  159. data/spec/support/cluster_config.rb +4 -0
  160. data/spec/support/event_subscriber.rb +123 -33
  161. data/spec/support/keyword_struct.rb +26 -0
  162. data/spec/support/shared/server_selector.rb +13 -1
  163. data/spec/support/spec_config.rb +38 -13
  164. data/spec/support/spec_organizer.rb +129 -0
  165. data/spec/support/spec_setup.rb +1 -1
  166. data/spec/support/utils.rb +46 -0
  167. metadata +992 -942
  168. metadata.gz.sig +0 -0
  169. data/lib/mongo/server_selector/selectable.rb +0 -560
  170. data/spec/runners/sdam_monitoring.rb +0 -89
@@ -127,13 +127,13 @@ describe 'CRUD operations' do
127
127
  describe 'upsert' do
128
128
  context 'with default write concern' do
129
129
  it 'upserts' do
130
- collection.count_documents({}).should == 0
130
+ collection.count_documents.should == 0
131
131
 
132
132
  res = collection.find(_id: 'foo').update_one({'$set' => {foo: 'bar'}}, upsert: true)
133
133
 
134
134
  res.documents.first['upserted'].length.should == 1
135
135
 
136
- collection.count_documents({}).should == 1
136
+ collection.count_documents.should == 1
137
137
  end
138
138
  end
139
139
 
@@ -147,7 +147,7 @@ describe 'CRUD operations' do
147
147
  end
148
148
 
149
149
  it 'upserts' do
150
- unack_collection.count_documents({}).should == 0
150
+ unack_collection.count_documents.should == 0
151
151
 
152
152
  res = unack_collection.find(_id: 'foo').update_one({'$set' => {foo: 'bar'}}, upsert: true)
153
153
 
@@ -155,7 +155,7 @@ describe 'CRUD operations' do
155
155
  # persisted (hopefully)
156
156
  sleep 0.25
157
157
 
158
- unack_collection.count_documents({}).should == 1
158
+ unack_collection.count_documents.should == 1
159
159
  end
160
160
  end
161
161
  end
@@ -1,6 +1,12 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe 'aggregation examples in Ruby' do
4
+ before(:all) do
5
+ # In sharded clusters we need to ensure the database exists before running
6
+ # the tests in this file.
7
+ ClientRegistry.instance.global_client('authorized')['_placeholder'].create
8
+ end
9
+
4
10
  let(:client) do
5
11
  authorized_client
6
12
  end
@@ -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,33 +1,14 @@
1
1
  require 'spec_helper'
2
2
 
3
- class TestHeartbeatSubscriber
4
- def initialize
5
- @started_events = []
6
- @succeeded_events = []
7
- @failed_events = []
8
- end
9
-
10
- attr_reader :started_events, :succeeded_events, :failed_events
11
-
12
- def started(event)
13
- @started_events << event
14
- end
15
-
16
- def succeeded(event)
17
- @succeeded_events << event
18
- end
19
-
20
- def failed(event)
21
- @failed_events << event
22
- end
23
- end
24
-
25
3
  describe 'Heartbeat events' do
26
4
  class HeartbeatEventsSpecTestException < StandardError; end
27
5
 
6
+ # 4.4 has two monitors and thus issues heartbeats multiple times
7
+ max_server_version '4.2'
8
+
28
9
  clean_slate_for_all
29
10
 
30
- let(:subscriber) { TestHeartbeatSubscriber.new }
11
+ let(:subscriber) { EventSubscriber.new }
31
12
 
32
13
  before do
33
14
  Mongo::Monitoring::Global.subscribe(Mongo::Monitoring::SERVER_HEARTBEAT, subscriber)
@@ -17,7 +17,7 @@ describe 'read concern' do
17
17
 
18
18
  let(:sent_read_concern) do
19
19
  subscriber.clear_events!
20
- collection.count_documents({})
20
+ collection.count_documents
21
21
  subscriber.started_events.find { |c| c.command_name == 'aggregate' }.command[:readConcern]
22
22
  end
23
23
 
@@ -106,7 +106,7 @@ describe 'Failing retryable operations' do
106
106
  },
107
107
  }
108
108
 
109
- if ClusterConfig.instance.short_server_version >= '4.3'
109
+ if ClusterConfig.instance.short_server_version >= '4.4'
110
110
  # Server versions 4.4 and newer will add the RetryableWriteError
111
111
  # label to all retryable errors, and the driver must not add the label
112
112
  # if it is not already present.
@@ -26,7 +26,7 @@ module PerformsLegacyRetries
26
26
  end
27
27
 
28
28
  context 'for ETIMEDOUT' do
29
- min_server_fcv '4.3'
29
+ min_server_fcv '4.4'
30
30
 
31
31
  # shorten socket timeout so these tests take less time to run
32
32
  let(:socket_timeout) { 1 }
@@ -59,7 +59,7 @@ module PerformsLegacyRetries
59
59
  end
60
60
 
61
61
  context 'on server versions >= 4.4' do
62
- min_server_fcv '4.3'
62
+ min_server_fcv '4.4'
63
63
 
64
64
  context 'for OperationFailure with RetryableWriteError label' do
65
65
  before do
@@ -44,8 +44,8 @@ module PerformsModernRetries
44
44
 
45
45
  context 'for ETIMEDOUT' do
46
46
  # blockConnection option in failCommand was introduced in
47
- # server version 4.3
48
- min_server_fcv '4.3'
47
+ # server version 4.4
48
+ min_server_fcv '4.4'
49
49
 
50
50
  # shorten socket timeout so these tests take less time to run
51
51
  let(:socket_timeout) { 1 }
@@ -94,7 +94,7 @@ module PerformsModernRetries
94
94
  end
95
95
 
96
96
  context 'on server versions >= 4.4' do
97
- min_server_fcv '4.3'
97
+ min_server_fcv '4.4'
98
98
 
99
99
  context 'for OperationFailure with RetryableWriteError label' do
100
100
  before do
@@ -25,7 +25,7 @@ module PerformsNoRetries
25
25
  end
26
26
 
27
27
  context 'for ETIMEDOUT' do
28
- min_server_fcv '4.3'
28
+ min_server_fcv '4.4'
29
29
 
30
30
  # shorten socket timeout so these tests take less time to run
31
31
  let(:socket_timeout) { 1 }
@@ -58,7 +58,7 @@ module PerformsNoRetries
58
58
  end
59
59
 
60
60
  context 'on server versions >= 4.4' do
61
- min_server_fcv '4.3'
61
+ min_server_fcv '4.4'
62
62
  # These tests will be implemented in a follow-up PR
63
63
  end
64
64
 
@@ -3,11 +3,27 @@ require 'spec_helper'
3
3
  describe 'SDAM error handling' do
4
4
  clean_slate_for_all
5
5
 
6
+ after do
7
+ # Close all clients after every test to avoid leaking expectations into
8
+ # subsequent tests because we set global assertions on sockets.
9
+ ClientRegistry.instance.close_all_clients
10
+ end
11
+
6
12
  # These tests operate on specific servers, and don't work in a multi
7
13
  # shard cluster where multiple servers are equally eligible
8
14
  require_no_multi_shard
9
15
 
10
- let(:client) { authorized_client_without_any_retries }
16
+ let(:diagnostic_subscriber) { VerboseEventSubscriber.new }
17
+
18
+ let(:client) do
19
+ new_local_client(SpecConfig.instance.addresses,
20
+ SpecConfig.instance.all_test_options.merge(
21
+ socket_timeout: 3, connect_timeout: 3,
22
+ # Uncomment to print all events to stdout:
23
+ #sdam_proc: Utils.subscribe_all_sdam_proc(diagnostic_subscriber),
24
+ **Utils.disable_retries_client_options)
25
+ )
26
+ end
11
27
 
12
28
  let(:server) { client.cluster.next_primary }
13
29
 
@@ -148,6 +164,9 @@ describe 'SDAM error handling' do
148
164
  end
149
165
 
150
166
  context 'network error' do
167
+ # With 4.4 servers we set up two monitoring connections, hence global
168
+ # socket expectations get hit twice.
169
+ max_server_version '4.2'
151
170
 
152
171
  let(:operation) do
153
172
  expect_any_instance_of(Mongo::Socket).to receive(:read).and_raise(exception)
@@ -181,13 +200,6 @@ describe 'SDAM error handling' do
181
200
  describe 'when there is an error on monitoring connection' do
182
201
  clean_slate_for_all
183
202
 
184
- let(:client) do
185
- new_local_client(SpecConfig.instance.addresses,
186
- SpecConfig.instance.test_options.merge(
187
- connect_timeout: 1, socket_timeout: 1,
188
- ))
189
- end
190
-
191
203
  let(:subscriber) { EventSubscriber.new }
192
204
 
193
205
  let(:set_subscribers) do
@@ -209,6 +221,7 @@ describe 'SDAM error handling' do
209
221
  it 'marks server unknown' do
210
222
  expect(server).not_to be_unknown
211
223
 
224
+ #subscriber.clear_events!
212
225
  events = subscriber.select_succeeded_events(Mongo::Monitoring::Event::ServerDescriptionChanged)
213
226
  events.should be_empty
214
227
 
@@ -228,6 +241,7 @@ describe 'SDAM error handling' do
228
241
 
229
242
  shared_examples_for 'clears connection pool - cmap event' do
230
243
  it 'clears connection pool' do
244
+ #subscriber.clear_events!
231
245
  events = subscriber.select_published_events(Mongo::Monitoring::Event::Cmap::PoolCleared)
232
246
  events.should be_empty
233
247
 
@@ -245,6 +259,7 @@ describe 'SDAM error handling' do
245
259
  end
246
260
 
247
261
  shared_examples_for 'marks server unknown and clears connection pool' do
262
+ =begin These tests are not reliable
248
263
  context 'via object inspection' do
249
264
  let(:expect_server_state_change) do
250
265
  server.summary.should =~ /unknown/i
@@ -254,6 +269,7 @@ describe 'SDAM error handling' do
254
269
  it_behaves_like 'marks server unknown'
255
270
  it_behaves_like 'clears connection pool'
256
271
  end
272
+ =end
257
273
 
258
274
  context 'via events' do
259
275
  # When we use events we do not need to examine object state, therefore
@@ -268,16 +284,22 @@ describe 'SDAM error handling' do
268
284
  end
269
285
  end
270
286
 
271
- context 'network timeout' do
272
- let(:exception) { Mongo::Error::SocketTimeoutError }
287
+ context 'via stubs' do
288
+ # With 4.4 servers we set up two monitoring connections, hence global
289
+ # socket expectations get hit twice.
290
+ max_server_version '4.2'
273
291
 
274
- it_behaves_like 'marks server unknown and clears connection pool'
275
- end
292
+ context 'network timeout' do
293
+ let(:exception) { Mongo::Error::SocketTimeoutError }
276
294
 
277
- context 'non-timeout network error' do
278
- let(:exception) { Mongo::Error::SocketError }
295
+ it_behaves_like 'marks server unknown and clears connection pool'
296
+ end
279
297
 
280
- it_behaves_like 'marks server unknown and clears connection pool'
298
+ context 'non-timeout network error' do
299
+ let(:exception) { Mongo::Error::SocketError }
300
+
301
+ it_behaves_like 'marks server unknown and clears connection pool'
302
+ end
281
303
  end
282
304
 
283
305
  context 'non-timeout network error via fail point' do
@@ -1,8 +1,7 @@
1
1
  require 'spec_helper'
2
- require 'runners/sdam_monitoring'
3
2
 
4
3
  describe 'SDAM events' do
5
- let(:subscriber) { Mongo::SDAMMonitoring::TestSubscriber.new }
4
+ let(:subscriber) { EventSubscriber.new }
6
5
 
7
6
  describe 'server closed event' do
8
7
  it 'is published when client is closed' do
@@ -12,11 +11,11 @@ describe 'SDAM events' do
12
11
 
13
12
  # get the client connected
14
13
  client.database.command(ismaster: 1)
15
- expect(subscriber.events).to be_empty
14
+ expect(subscriber.succeeded_events).to be_empty
16
15
 
17
16
  client.close
18
17
 
19
- expect(subscriber.events).not_to be_empty
18
+ expect(subscriber.succeeded_events).not_to be_empty
20
19
  event = subscriber.first_event('server_closed_event')
21
20
  expect(event).not_to be_nil
22
21
  end
@@ -30,15 +29,87 @@ describe 'SDAM events' do
30
29
 
31
30
  # get the client connected
32
31
  client.database.command(ismaster: 1)
33
- expect(subscriber.events).to be_empty
32
+ expect(subscriber.succeeded_events).to be_empty
34
33
 
35
34
  client.close
36
35
 
37
- expect(subscriber.events).not_to be_empty
36
+ expect(subscriber.succeeded_events).not_to be_empty
38
37
  event = subscriber.first_event('topology_closed_event')
39
38
  expect(event).not_to be_nil
40
39
 
41
40
  expect(event.topology).to eql(client.cluster.topology)
42
41
  end
43
42
  end
43
+
44
+ describe 'heartbeat event' do
45
+ require_topology :single
46
+
47
+ context 'pre-4.4 servers' do
48
+ max_server_version '4.2'
49
+
50
+ let(:client) do
51
+ new_local_client(SpecConfig.instance.addresses,
52
+ # Heartbeat interval is bound by 500 ms
53
+ SpecConfig.instance.test_options.merge(heartbeat_frequency: 0.5),
54
+ ).tap do |client|
55
+ client.subscribe(Mongo::Monitoring::SERVER_HEARTBEAT, subscriber)
56
+ end
57
+ end
58
+
59
+ it 'is published every heartbeat interval' do
60
+ client
61
+ sleep 4
62
+ client.close
63
+
64
+ started_events = subscriber.select_started_events(Mongo::Monitoring::Event::ServerHeartbeatStarted)
65
+ # Expect about 8 events, maybe 9 or 7
66
+ started_events.length.should >= 6
67
+ started_events.length.should <= 10
68
+
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
+ started_events.length.should == succeeded_events.length
73
+ end
74
+ end
75
+
76
+ context '4.4+ servers' do
77
+ min_server_fcv '4.4'
78
+
79
+ let(:client) do
80
+ new_local_client(SpecConfig.instance.addresses,
81
+ # Heartbeat interval is bound by 500 ms
82
+ SpecConfig.instance.test_options.merge(heartbeat_frequency: 0.5),
83
+ ).tap do |client|
84
+ client.subscribe(Mongo::Monitoring::SERVER_HEARTBEAT, subscriber)
85
+ end
86
+ end
87
+
88
+ it 'is published up to twice every heartbeat interval' do
89
+ client
90
+ sleep 3
91
+ client.close
92
+
93
+ events = subscriber.select_started_events(Mongo::Monitoring::Event::ServerHeartbeatStarted)
94
+ # We could have up to 16 events and should have no fewer than 8 events.
95
+ # Whenever an awaited ismaster succeeds while the regular monitor is
96
+ # waiting, the regular monitor's next scan is pushed forward.
97
+ events.length.should >= 6
98
+ events.length.should <= 18
99
+ (started_awaited = events.select(&:awaited?)).should_not be_empty
100
+ (started_regular = events.reject(&:awaited?)).should_not be_empty
101
+
102
+ events = subscriber.select_succeeded_events(Mongo::Monitoring::Event::ServerHeartbeatSucceeded)
103
+ events.length.should >= 6
104
+ events.length.should <= 18
105
+ (succeeded_awaited = events.select(&:awaited?)).should_not be_empty
106
+ (succeeded_regular = events.reject(&:awaited?)).should_not be_empty
107
+
108
+ # Since we gracefully close the client, we expect each heartbeat
109
+ # to complete.
110
+ started_awaited.length.should == succeeded_awaited.length
111
+ started_regular.length.should == succeeded_regular.length
112
+ end
113
+ end
114
+ end
44
115
  end
@@ -0,0 +1,64 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'SDAM prose tests' do
4
+ # The "streaming protocol tests" are covered by the tests in
5
+ # sdam_events_spec.rb.
6
+
7
+ describe 'RTT tests' do
8
+ min_server_fcv '4.4'
9
+ require_topology :single
10
+
11
+ let(:subscriber) { EventSubscriber.new }
12
+
13
+ let(:client) do
14
+ new_local_client(SpecConfig.instance.addresses,
15
+ # Heartbeat interval is bound by 500 ms
16
+ SpecConfig.instance.test_options.merge(
17
+ heartbeat_frequency: 0.5,
18
+ app_name: 'streamingRttTest',
19
+ ),
20
+ ).tap do |client|
21
+ client.subscribe(Mongo::Monitoring::SERVER_HEARTBEAT, subscriber)
22
+ end
23
+ end
24
+
25
+ it 'updates RTT' do
26
+ server = client.cluster.next_primary
27
+
28
+ sleep 2
29
+
30
+ events = subscriber.select_succeeded_events(Mongo::Monitoring::Event::ServerHeartbeatSucceeded)
31
+ events.each do |event|
32
+ event.round_trip_time.should be_a(Numeric)
33
+ event.round_trip_time.should > 0
34
+ end
35
+
36
+ root_authorized_client.use('admin').database.command(
37
+ configureFailPoint: 'failCommand',
38
+ mode: {times: 1000},
39
+ data: {
40
+ failCommands: ["isMaster"],
41
+ blockConnection: true,
42
+ blockTimeMS: 500,
43
+ appName: "streamingRttTest",
44
+ },
45
+ )
46
+
47
+ deadline = Time.now + 10
48
+ loop do
49
+ if server.average_round_trip_time > 0.25
50
+ break
51
+ end
52
+ if Time.now >= deadline
53
+ raise "Failed to witness RTT growing to >= 250 ms in 10 seconds"
54
+ end
55
+ sleep 0.2
56
+ end
57
+ end
58
+
59
+ after do
60
+ root_authorized_client.use('admin').database.command(
61
+ configureFailPoint: 'failCommand', mode: 'off')
62
+ end
63
+ end
64
+ end