mongo 2.7.0 → 2.7.1

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 (125) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +0 -0
  4. data/README.md +39 -14
  5. data/Rakefile +1 -0
  6. data/lib/mongo/auth.rb +4 -1
  7. data/lib/mongo/client.rb +4 -3
  8. data/lib/mongo/cluster.rb +1 -1
  9. data/lib/mongo/collection/view/readable.rb +5 -2
  10. data/lib/mongo/database.rb +1 -0
  11. data/lib/mongo/error/invalid_server_preference.rb +1 -0
  12. data/lib/mongo/error/operation_failure.rb +10 -0
  13. data/lib/mongo/error/parser.rb +10 -0
  14. data/lib/mongo/event.rb +1 -2
  15. data/lib/mongo/operation/result.rb +4 -1
  16. data/lib/mongo/operation/shared/executable_transaction_label.rb +3 -1
  17. data/lib/mongo/operation/shared/sessions_supported.rb +1 -1
  18. data/lib/mongo/protocol/msg.rb +1 -1
  19. data/lib/mongo/protocol/query.rb +2 -2
  20. data/lib/mongo/retryable.rb +20 -6
  21. data/lib/mongo/server.rb +6 -0
  22. data/lib/mongo/server/connection.rb +4 -4
  23. data/lib/mongo/server/monitor/connection.rb +9 -5
  24. data/lib/mongo/server_selector/selectable.rb +86 -32
  25. data/lib/mongo/session.rb +98 -15
  26. data/lib/mongo/version.rb +1 -1
  27. data/spec/README.md +85 -0
  28. data/spec/integration/bulk_insert_spec.rb +1 -1
  29. data/spec/integration/change_stream_examples_spec.rb +3 -1
  30. data/spec/integration/change_stream_spec.rb +10 -14
  31. data/spec/integration/client_construction_spec.rb +1 -0
  32. data/spec/integration/command_monitoring_spec.rb +37 -1
  33. data/spec/integration/command_spec.rb +141 -0
  34. data/spec/integration/connection_spec.rb +4 -2
  35. data/spec/integration/cursor_reaping_spec.rb +1 -1
  36. data/spec/integration/docs_examples_spec.rb +1 -1
  37. data/spec/integration/retryable_writes_spec.rb +33 -42
  38. data/spec/integration/server_description_spec.rb +3 -3
  39. data/spec/integration/server_selector_spec.rb +79 -0
  40. data/spec/lite_spec_helper.rb +4 -2
  41. data/spec/mongo/address_spec.rb +8 -0
  42. data/spec/mongo/auth/cr_spec.rb +5 -2
  43. data/spec/mongo/auth/invalid_mechanism_spec.rb +11 -0
  44. data/spec/mongo/auth/scram/conversation_spec.rb +3 -2
  45. data/spec/mongo/auth/scram/negotiation_spec.rb +1 -2
  46. data/spec/mongo/auth/scram_spec.rb +11 -6
  47. data/spec/mongo/auth/user/view_spec.rb +13 -6
  48. data/spec/mongo/bulk_write_spec.rb +81 -104
  49. data/spec/mongo/client_construction_spec.rb +18 -7
  50. data/spec/mongo/client_spec.rb +11 -7
  51. data/spec/mongo/cluster_spec.rb +30 -1
  52. data/spec/mongo/collection/view/aggregation_spec.rb +18 -10
  53. data/spec/mongo/collection/view/change_stream_spec.rb +28 -8
  54. data/spec/mongo/collection/view/map_reduce_spec.rb +24 -10
  55. data/spec/mongo/collection/view/readable_spec.rb +37 -19
  56. data/spec/mongo/collection/view/writable_spec.rb +64 -32
  57. data/spec/mongo/collection/view_spec.rb +4 -2
  58. data/spec/mongo/collection_spec.rb +163 -73
  59. data/spec/mongo/cursor_spec.rb +5 -2
  60. data/spec/mongo/database_spec.rb +41 -19
  61. data/spec/mongo/error/no_server_available_spec.rb +1 -1
  62. data/spec/mongo/error/parser_spec.rb +29 -0
  63. data/spec/mongo/grid/stream/write_spec.rb +2 -1
  64. data/spec/mongo/index/view_spec.rb +42 -24
  65. data/spec/mongo/operation/delete/op_msg_spec.rb +11 -7
  66. data/spec/mongo/operation/insert/op_msg_spec.rb +10 -6
  67. data/spec/mongo/operation/update/op_msg_spec.rb +10 -6
  68. data/spec/mongo/protocol/compressed_spec.rb +1 -1
  69. data/spec/mongo/protocol/msg_spec.rb +1 -1
  70. data/spec/mongo/server/app_metadata_spec.rb +2 -1
  71. data/spec/mongo/server/connection_auth_spec.rb +1 -1
  72. data/spec/mongo/server/monitor/connection_spec.rb +42 -0
  73. data/spec/mongo/server_selector_spec.rb +17 -0
  74. data/spec/mongo/server_spec.rb +110 -0
  75. data/spec/mongo/session/session_pool_spec.rb +1 -1
  76. data/spec/mongo/session_spec.rb +1 -1
  77. data/spec/mongo/session_transaction_spec.rb +162 -1
  78. data/spec/mongo/socket/ssl_spec.rb +14 -7
  79. data/spec/mongo/uri/srv_protocol_spec.rb +41 -34
  80. data/spec/spec_helper.rb +3 -191
  81. data/spec/spec_tests/change_streams_spec.rb +3 -6
  82. data/spec/spec_tests/data/transactions/abort.yml +3 -1
  83. data/spec/spec_tests/data/transactions/commit.yml +4 -3
  84. data/spec/spec_tests/data/transactions/error-labels.yml +17 -13
  85. data/spec/spec_tests/data/transactions/read-concern.yml +611 -0
  86. data/spec/spec_tests/data/transactions/retryable-commit.yml +126 -21
  87. data/spec/spec_tests/data/transactions_api/callback-aborts.yml +42 -39
  88. data/spec/spec_tests/data/transactions_api/callback-commits.yml +52 -50
  89. data/spec/spec_tests/data/transactions_api/callback-retry.yml +33 -31
  90. data/spec/spec_tests/data/transactions_api/commit-retry.yml +42 -39
  91. data/spec/spec_tests/data/transactions_api/commit-transienttransactionerror-4.2.yml +13 -12
  92. data/spec/spec_tests/data/transactions_api/commit-transienttransactionerror.yml +15 -26
  93. data/spec/spec_tests/data/transactions_api/commit-writeconcernerror.yml +25 -33
  94. data/spec/spec_tests/data/transactions_api/commit.yml +44 -42
  95. data/spec/spec_tests/data/transactions_api/transaction-options.yml +25 -23
  96. data/spec/spec_tests/max_staleness_spec.rb +2 -0
  97. data/spec/spec_tests/retryable_writes_spec.rb +2 -6
  98. data/spec/spec_tests/sdam_spec.rb +2 -0
  99. data/spec/spec_tests/server_selection_spec.rb +3 -0
  100. data/spec/spec_tests/transactions_api_spec.rb +7 -1
  101. data/spec/spec_tests/transactions_spec.rb +6 -0
  102. data/spec/spec_tests/uri_options_spec.rb +4 -26
  103. data/spec/support/certificates/ca.pem +21 -16
  104. data/spec/support/certificates/client.pem +90 -90
  105. data/spec/support/certificates/client_cert.pem +21 -20
  106. data/spec/support/certificates/client_key.pem +27 -28
  107. data/spec/support/certificates/client_key_encrypted.pem +26 -26
  108. data/spec/support/certificates/crl.pem +10 -8
  109. data/spec/support/certificates/crl_client_revoked.pem +11 -10
  110. data/spec/support/certificates/server.pem +48 -33
  111. data/spec/support/change_streams.rb +12 -32
  112. data/spec/support/client_registry.rb +12 -1
  113. data/spec/support/cluster_config.rb +48 -2
  114. data/spec/support/common_shortcuts.rb +73 -7
  115. data/spec/support/connection_string.rb +0 -3
  116. data/spec/support/constraints.rb +87 -22
  117. data/spec/support/crud.rb +2 -1
  118. data/spec/support/shared/server_selector.rb +0 -28
  119. data/spec/support/shared/session.rb +25 -14
  120. data/spec/support/transactions.rb +4 -8
  121. data/spec/support/transactions/operation.rb +26 -4
  122. data/spec/support/transactions/verifier.rb +5 -2
  123. metadata +496 -488
  124. metadata.gz.sig +5 -2
  125. data/spec/support/certificates/password_protected.pem +0 -51
@@ -55,7 +55,7 @@ describe 'Bulk insert' do
55
55
  end
56
56
 
57
57
  context 'entire operation fails' do
58
- min_server_version '4.0'
58
+ min_server_fcv '4.0'
59
59
  require_topology :single, :replica_set
60
60
 
61
61
  it 'is an empty array' do
@@ -1,6 +1,8 @@
1
1
  require 'spec_helper'
2
2
 
3
- describe 'change streams examples in Ruby', if: test_change_streams? do
3
+ describe 'change streams examples in Ruby' do
4
+ min_server_fcv '3.6'
5
+ require_topology :replica_set
4
6
 
5
7
  let!(:inventory) do
6
8
  client[:inventory]
@@ -3,6 +3,8 @@ require 'spec_helper'
3
3
  describe 'Change stream integration', retry: 4 do
4
4
  only_mri
5
5
  max_example_run_time 7
6
+ min_server_fcv '3.6'
7
+ require_topology :replica_set
6
8
 
7
9
  let(:fail_point_base_command) do
8
10
  { 'configureFailPoint' => "failCommand" }
@@ -23,12 +25,6 @@ describe 'Change stream integration', retry: 4 do
23
25
  end
24
26
  end
25
27
 
26
- before do
27
- unless test_change_streams?
28
- skip 'Not testing change streams'
29
- end
30
- end
31
-
32
28
  describe 'watch+next' do
33
29
  let(:change_stream) { authorized_collection.watch }
34
30
 
@@ -66,7 +62,7 @@ describe 'Change stream integration', retry: 4 do
66
62
  end
67
63
 
68
64
  context 'error on initial aggregation' do
69
- min_server_version '4.0'
65
+ min_server_fcv '4.0'
70
66
  clear_fail_point_before
71
67
 
72
68
  before do
@@ -83,7 +79,7 @@ describe 'Change stream integration', retry: 4 do
83
79
  end
84
80
 
85
81
  context 'one error on getMore' do
86
- min_server_version '4.0'
82
+ min_server_fcv '4.0'
87
83
  clear_fail_point_before
88
84
 
89
85
  context 'error on first getMore' do
@@ -117,7 +113,7 @@ describe 'Change stream integration', retry: 4 do
117
113
  end
118
114
 
119
115
  context 'two errors on getMore' do
120
- min_server_version '4.0'
116
+ min_server_fcv '4.0'
121
117
  clear_fail_point_before
122
118
 
123
119
  context 'error of first getMores' do
@@ -155,7 +151,7 @@ describe 'Change stream integration', retry: 4 do
155
151
  end
156
152
 
157
153
  context 'two errors on getMore followed by an error on aggregation' do
158
- min_server_version '4.0'
154
+ min_server_fcv '4.0'
159
155
  clear_fail_point_before
160
156
 
161
157
  it 'next raises error' do
@@ -215,7 +211,7 @@ describe 'Change stream integration', retry: 4 do
215
211
  end
216
212
 
217
213
  context 'one error on getMore' do
218
- min_server_version '4.0'
214
+ min_server_fcv '4.0'
219
215
  clear_fail_point_before
220
216
 
221
217
  context 'error on first getMore' do
@@ -245,7 +241,7 @@ describe 'Change stream integration', retry: 4 do
245
241
  end
246
242
 
247
243
  context 'two errors on getMore' do
248
- min_server_version '4.0'
244
+ min_server_fcv '4.0'
249
245
  clear_fail_point_before
250
246
 
251
247
  before do
@@ -265,7 +261,7 @@ describe 'Change stream integration', retry: 4 do
265
261
  end
266
262
 
267
263
  context 'two errors on getMore followed by an error on aggregation' do
268
- min_server_version '4.0'
264
+ min_server_fcv '4.0'
269
265
  clear_fail_point_before
270
266
 
271
267
  context 'error on first getMore' do
@@ -316,7 +312,7 @@ describe 'Change stream integration', retry: 4 do
316
312
  end
317
313
 
318
314
  describe ':start_at_operation_time option' do
319
- min_server_version '4.0'
315
+ min_server_fcv '4.0'
320
316
 
321
317
  before do
322
318
  authorized_collection.delete_many
@@ -5,6 +5,7 @@ require 'spec_helper'
5
5
  describe 'Client construction' do
6
6
  let(:base_options) do
7
7
  SpecConfig.instance.test_options.merge(
8
+ server_selection_timeout: 5,
8
9
  database: SpecConfig.instance.test_db,
9
10
  user: SpecConfig.instance.test_user.name,
10
11
  password: SpecConfig.instance.test_user.password)
@@ -68,7 +68,7 @@ describe 'Command monitoring' do
68
68
  context 'client with no established connections' do
69
69
  # for simplicity use 3.6+ servers only, then we can assert
70
70
  # scram auth commands
71
- min_server_version '3.6'
71
+ min_server_fcv '3.6'
72
72
 
73
73
  it 'does not nest auth and find' do
74
74
  expect(subscriber.started_events.length).to eq 0
@@ -77,4 +77,40 @@ describe 'Command monitoring' do
77
77
  expect(command_names).to eq %w(saslStart saslContinue saslContinue find)
78
78
  end
79
79
  end
80
+
81
+ context 'when write concern is specified outside of command document' do
82
+ require_topology :replica_set
83
+ min_server_fcv '4.0'
84
+
85
+ let(:collection) do
86
+ client['command-monitoring-test']
87
+ end
88
+ let(:write_concern) { Mongo::WriteConcern.get({w: 42}) }
89
+ let(:session) { client.start_session }
90
+ let(:command) do
91
+ Mongo::Operation::Command.new(
92
+ selector: { commitTransaction: 1 },
93
+ db_name: 'admin',
94
+ session: session,
95
+ txn_num: 123,
96
+ write_concern: write_concern,
97
+ )
98
+ end
99
+
100
+ it 'includes write concern in notified command document' do
101
+ server = client.cluster.next_primary
102
+ collection.insert_one(a: 1)
103
+ session.start_transaction
104
+ collection.insert_one({a: 1}, session: session)
105
+
106
+ subscriber.clear_events!
107
+ expect do
108
+ command.execute(server)
109
+ end.to raise_error(Mongo::Error::OperationFailure, 'Not enough data-bearing nodes (100)')
110
+
111
+ expect(subscriber.started_events.length).to eq(1)
112
+ event = subscriber.started_events.first
113
+ expect(event.command['writeConcern']['w']).to eq(42)
114
+ end
115
+ end
80
116
  end
@@ -0,0 +1,141 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'Command' do
4
+
5
+ let(:subscriber) { EventSubscriber.new }
6
+
7
+ describe 'payload' do
8
+ let(:server) { authorized_client.cluster.next_primary }
9
+
10
+ let(:payload) do
11
+ command.send(:final_operation, server).send(:message, server).payload.dup.tap do |payload|
12
+ if payload['request_id'].is_a?(Integer)
13
+ payload['request_id'] = 42
14
+ end
15
+ # $clusterTime may be present depending on the client's state
16
+ payload['command'].delete('$clusterTime')
17
+ # 3.6+ servers also return a payload field, earlier ones do not.
18
+ # The contents of this field duplicates the rest of the response
19
+ # so we can get rid of it without losing information.
20
+ payload.delete('reply')
21
+ end
22
+ end
23
+
24
+ let(:session) { nil }
25
+
26
+ context 'commitTransaction' do
27
+ # Although these are unit tests, when targeting pre-4.0 servers
28
+ # the driver does not add arguments like write concerns to commands that
29
+ # it adds for 4.0+ servers, breaking expectations
30
+ min_server_fcv '4.0'
31
+
32
+ let(:selector) do
33
+ { commitTransaction: 1 }.freeze
34
+ end
35
+
36
+ let(:write_concern) { nil }
37
+
38
+ let(:command) do
39
+ Mongo::Operation::Command.new(
40
+ selector: selector,
41
+ db_name: 'admin',
42
+ session: session,
43
+ txn_num: 123,
44
+ write_concern: write_concern,
45
+ )
46
+ end
47
+
48
+ let(:expected_payload) do
49
+ {
50
+ 'command' => {'commitTransaction' => 1},
51
+ 'command_name' => 'commitTransaction',
52
+ 'database_name' => 'admin',
53
+ 'request_id' => 42,
54
+ }
55
+ end
56
+
57
+ it 'returns expected payload' do
58
+ expect(payload).to eq(expected_payload)
59
+ end
60
+
61
+ context 'with session' do
62
+ min_server_fcv '3.6'
63
+
64
+ let(:session) { authorized_client.start_session }
65
+ # w will be 2 for a RS topology with 3 nodes
66
+ let(:w) do
67
+ authorized_client.write_concern.options[:w].tap do |w|
68
+ expect(w).to be_a(Integer)
69
+ end
70
+ end
71
+
72
+ let(:expected_payload) do
73
+ {
74
+ 'command' => {
75
+ 'commitTransaction' => 1,
76
+ 'lsid' => session.session_id,
77
+ 'txnNumber' => BSON::Int64.new(123),
78
+ 'writeConcern' => {'w' => w},
79
+ },
80
+ 'command_name' => 'commitTransaction',
81
+ 'database_name' => 'admin',
82
+ 'request_id' => 42,
83
+ }
84
+ end
85
+
86
+ it 'returns selector with write concern' do
87
+ expect(payload).to eq(expected_payload)
88
+ end
89
+ end
90
+
91
+ context 'with write concern' do
92
+ let(:write_concern) { Mongo::WriteConcern.get(w: :majority) }
93
+
94
+ let(:expected_payload) do
95
+ {
96
+ 'command' => {
97
+ 'commitTransaction' => 1,
98
+ 'writeConcern' => {'w' => 'majority'},
99
+ },
100
+ 'command_name' => 'commitTransaction',
101
+ 'database_name' => 'admin',
102
+ 'request_id' => 42,
103
+ }
104
+ end
105
+
106
+ it 'returns selector with write concern' do
107
+ expect(payload).to eq(expected_payload)
108
+ end
109
+ end
110
+ end
111
+
112
+ context 'find' do
113
+ let(:selector) do
114
+ { find: 'collection_name' }.freeze
115
+ end
116
+
117
+ let(:command) do
118
+ Mongo::Operation::Command.new(
119
+ selector: selector,
120
+ db_name: 'foo',
121
+ session: session,
122
+ )
123
+ end
124
+
125
+ let(:expected_payload) do
126
+ {
127
+ 'command' => {'find' => 'collection_name'},
128
+ 'command_name' => 'find',
129
+ 'database_name' => 'foo',
130
+ 'request_id' => 42,
131
+ }
132
+ end
133
+
134
+ it 'returns expected payload' do
135
+ expect(payload).to eq(expected_payload)
136
+ end
137
+ end
138
+
139
+ end
140
+
141
+ end
@@ -48,6 +48,8 @@ describe 'Connections' do
48
48
  it 'publishes server description changed event' do
49
49
  expect(subscriber.events).to be_empty
50
50
 
51
+ wait_for_all_servers(client.cluster)
52
+
51
53
  connection
52
54
  subscriber.events.clear
53
55
  error
@@ -94,7 +96,7 @@ describe 'Connections' do
94
96
  end
95
97
 
96
98
  context 'error during handshake to primary in a replica set' do
97
- require_topology 'replica_set'
99
+ require_topology :replica_set
98
100
 
99
101
  let(:server) { client.cluster.servers.detect { |server| server.primary? } }
100
102
 
@@ -119,7 +121,7 @@ describe 'Connections' do
119
121
  # which is not supported by modern mongos.
120
122
  # Instead of mucking with this we just limit this test to 3.2+
121
123
  # so that we can downgrade protocol range to 0..3 instead of 0..1.
122
- min_server_version '3.2'
124
+ min_server_fcv '3.2'
123
125
 
124
126
  let(:client) { ClientRegistry.instance.global_client('authorized').with(app_name: 'wire_protocol_update') }
125
127
 
@@ -80,7 +80,7 @@ describe 'Cursor reaping' do
80
80
  end
81
81
 
82
82
  context 'newer servers' do
83
- min_server_version '3.2'
83
+ min_server_fcv '3.2'
84
84
 
85
85
  it 'is really killed' do
86
86
  cursor_id, event = cursor_id_and_kill_event
@@ -91,7 +91,7 @@ describe 'aggregation examples in Ruby' do
91
91
  end
92
92
 
93
93
  context 'Aggregation Example 4 - $lookup, $filter, $match' do
94
- min_server_version '3.6'
94
+ min_server_fcv '3.6'
95
95
 
96
96
  let(:example_code) do
97
97
 
@@ -299,6 +299,37 @@ describe 'Retryable writes integration tests' do
299
299
  end
300
300
  end
301
301
 
302
+ shared_examples_for 'operation that is retried when server supports retryable writes' do
303
+ context 'when the server supports retryable writes' do
304
+ min_server_fcv '3.6'
305
+
306
+ before do
307
+ allow(primary_server).to receive(:retry_writes?).and_return(true)
308
+ end
309
+
310
+ context 'standalone' do
311
+ require_topology :single
312
+
313
+ it_behaves_like 'an operation that is not retried'
314
+ end
315
+
316
+ context 'replica set or sharded cluster' do
317
+ require_topology :replica_set, :sharded
318
+
319
+ it_behaves_like 'an operation that is retried'
320
+ end
321
+ end
322
+
323
+ context 'when the server does not support retryable writes' do
324
+
325
+ before do
326
+ allow(primary_server).to receive(:retry_writes?).and_return(false)
327
+ end
328
+
329
+ it_behaves_like 'an operation that is not retried'
330
+ end
331
+ end
332
+
302
333
  shared_examples_for 'supported retryable writes' do
303
334
 
304
335
  context 'when the client has retry_writes set to true' do
@@ -313,27 +344,7 @@ describe 'Retryable writes integration tests' do
313
344
  client[TEST_COLL, write: SpecConfig.instance.write_concern]
314
345
  end
315
346
 
316
- context 'when the server supports retryable writes' do
317
-
318
- before do
319
- allow(primary_server).to receive(:retry_writes?).and_return(true)
320
- end
321
-
322
- if standalone? && sessions_enabled?
323
- it_behaves_like 'an operation that is not retried'
324
- elsif sessions_enabled?
325
- it_behaves_like 'an operation that is retried'
326
- end
327
- end
328
-
329
- context 'when the server does not support retryable writes' do
330
-
331
- before do
332
- allow(primary_server).to receive(:retry_writes?).and_return(false)
333
- end
334
-
335
- it_behaves_like 'an operation that is not retried'
336
- end
347
+ it_behaves_like 'operation that is retried when server supports retryable writes'
337
348
  end
338
349
 
339
350
  context 'when the collection has write concern unacknowledged' do
@@ -351,27 +362,7 @@ describe 'Retryable writes integration tests' do
351
362
  client[TEST_COLL]
352
363
  end
353
364
 
354
- context 'when the server supports retryable writes' do
355
-
356
- before do
357
- allow(primary_server).to receive(:retry_writes?).and_return(true)
358
- end
359
-
360
- if standalone? && sessions_enabled?
361
- it_behaves_like 'an operation that is not retried'
362
- elsif sessions_enabled?
363
- it_behaves_like 'an operation that is retried'
364
- end
365
- end
366
-
367
- context 'when the server does not support retryable writes' do
368
-
369
- before do
370
- allow(primary_server).to receive(:retry_writes?).and_return(false)
371
- end
372
-
373
- it_behaves_like 'an operation that is not retried'
374
- end
365
+ it_behaves_like 'operation that is retried when server supports retryable writes'
375
366
  end
376
367
  end
377
368