mongo 2.7.0 → 2.7.1

Sign up to get free protection for your applications and to get access to all the features.
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