mongo 2.10.0 → 2.10.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1a1e6b0cb6b8548601a5ad4c4758361f9815d65750b52fef6b2393eb09ab5ae4
4
- data.tar.gz: '084a8d5a64bba3ffaab853919918f9cb214754edbaec4ac22eeaee5e9954f39b'
3
+ metadata.gz: 18e71f41caf0b6b8c618c8ea7cedb903ca10248949993c6c25ebf61d6acf3bba
4
+ data.tar.gz: bd587a35aadbaf790b61c83867f276bd13858c6469fb8ef26bf3907e58a5703a
5
5
  SHA512:
6
- metadata.gz: 19fc6811951a53cfef86d647849337fb56014e97d2cf9aec0ea0de58f3525632a96e04c1f5a6ecd4f6de8f7a853faded939e59f716d9fa4a6c9ac40a7e742ce9
7
- data.tar.gz: '08ff4b626997aa23fb9db94893818e2326cc2c13032ea4dabf512628b436597f13a2c69a2693d57fd58d60208c384660b4c811ca98b8aeb1a47994b212a0dbd5'
6
+ metadata.gz: c923c55b783fb6d0a37d90116684afe65c038d1d7c06dfa1ace59a825eeee441ad7384f42ab45cb47bc7f2abedc16faef6f5f8adef68751631dcc57ddbca8be1
7
+ data.tar.gz: bff45797b2533f2d842787c9c1d63eef76deab4471244af4d759237ab122b70d3c785d2ad064bf0b79e3d045c86efa5f6f7f47e4b8cdec5607b95ffd323400d3
@@ -1,2 +1,3 @@
1
- ��B��H��\v0��m1h]CQ-Ҥق�H��_ u����l��*ί���B�|���Z9��{ҡ��<Y��
2
- h0MΓ��H��o��"w�;{c�sȄ��/��D!�)'�#�Pcf�r���R`����\'ז�S�SZD�
1
+ *܉o]���GO�=��S��rhc�ug�0D����}D����җoC&AH�N� �9)s����(��p��qodh^_���pZL)J(m�lܫ��p駴�x���#Fƻkf!��3f�j�0"ٖ|繣��Zy����?j��j�����Бd�1(2�������[D<��ޒ�9���l���m"R
2
+ �"�G�~����:��
3
+ q_���=��y=�|�Т[���-�����ވ���`��+Vf!
data.tar.gz.sig CHANGED
Binary file
@@ -23,7 +23,7 @@ require 'mongo/bulk_write/result_combiner'
23
23
  module Mongo
24
24
  class BulkWrite
25
25
  extend Forwardable
26
- include Operation::Unpinnable
26
+ include Operation::ResponseHandling
27
27
 
28
28
  # @return [ Mongo::Collection ] collection The collection.
29
29
  attr_reader :collection
@@ -12,11 +12,14 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
 
15
+ require 'mongo/error/notable'
16
+
15
17
  module Mongo
16
18
  # Base error class for all Mongo related errors.
17
19
  #
18
20
  # @since 2.0.0
19
21
  class Error < StandardError
22
+ include Notable
20
23
 
21
24
  # The error code field.
22
25
  #
@@ -141,6 +144,7 @@ module Mongo
141
144
  end
142
145
  end
143
146
 
147
+ require 'mongo/error/auth_error'
144
148
  require 'mongo/error/sdam_error_detection'
145
149
  require 'mongo/error/parser'
146
150
  require 'mongo/error/write_retryable'
@@ -0,0 +1,29 @@
1
+ # Copyright (C) 2018-2019 MongoDB, Inc.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ module Mongo
16
+ class Error
17
+
18
+ # Raised when authentication fails.
19
+ #
20
+ # Note: This class is derived from RuntimeError for
21
+ # backwards compatibility reasons. It is subject to
22
+ # change in future major versions of the driver.
23
+ #
24
+ # @since 2.10.1
25
+ class AuthError < RuntimeError
26
+ include Notable
27
+ end
28
+ end
29
+ end
@@ -50,7 +50,7 @@ module Mongo
50
50
  else
51
51
  ''
52
52
  end
53
- self.class.name + messages
53
+ "#{self.class}: #{messages}" + notes_tail
54
54
  end
55
55
  end
56
56
  end
@@ -0,0 +1,80 @@
1
+ # Copyright (C) 2019 MongoDB, Inc.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ module Mongo
16
+ class Error < StandardError
17
+
18
+ # A module encapsulating note tracking functionality, since currently
19
+ # the driver does not have a single exception hierarchy root.
20
+ #
21
+ # @since 2.10.1
22
+ # @api private
23
+ module Notable
24
+
25
+ # Returns an array of strings with additional information about the
26
+ # exception.
27
+ #
28
+ # @return [ Array<String> ] Additional information strings.
29
+ #
30
+ # @since 2.10.1
31
+ # @api public
32
+ def notes
33
+ if @notes
34
+ @notes.dup
35
+ else
36
+ []
37
+ end
38
+ end
39
+
40
+ # @api private
41
+ def add_note(note)
42
+ unless @notes
43
+ @notes = []
44
+ end
45
+ @notes << note
46
+ end
47
+
48
+ # @api public
49
+ def message
50
+ super + notes_tail
51
+ end
52
+
53
+ # @api public
54
+ def to_s
55
+ super + notes_tail
56
+ end
57
+
58
+ # @api public
59
+ def inspect
60
+ msg = super
61
+ if msg.end_with?('>')
62
+ msg[0...msg.length-1] + notes_tail + '>'
63
+ else
64
+ msg + notes_tail
65
+ end
66
+ end
67
+
68
+ private
69
+
70
+ # @api private
71
+ def notes_tail
72
+ msg = ''
73
+ unless notes.empty?
74
+ msg += " (#{notes.join(', ')})"
75
+ end
76
+ msg
77
+ end
78
+ end
79
+ end
80
+ end
@@ -1,5 +1,6 @@
1
1
  require 'mongo/operation/result'
2
2
 
3
+ require 'mongo/operation/shared/response_handling'
3
4
  require 'mongo/operation/shared/executable'
4
5
  require 'mongo/operation/shared/executable_no_validate'
5
6
  require 'mongo/operation/shared/executable_transaction_label'
@@ -13,7 +14,6 @@ require 'mongo/operation/shared/sessions_supported'
13
14
  require 'mongo/operation/shared/causal_consistency_supported'
14
15
  require 'mongo/operation/shared/write'
15
16
  require 'mongo/operation/shared/idable'
16
- require 'mongo/operation/shared/unpinnable'
17
17
  require 'mongo/operation/shared/specifiable'
18
18
  require 'mongo/operation/shared/object_id_generator'
19
19
  require 'mongo/operation/shared/op_msg_or_command'
@@ -24,28 +24,18 @@ module Mongo
24
24
  class Command
25
25
  include Specifiable
26
26
  include Executable
27
+ include ExecutableNoValidate
27
28
  include Idable
28
29
  include Limited
29
30
  include WriteConcernSupported
30
31
  include BypassDocumentValidation
31
32
 
32
- # Execute the operation.
33
- #
34
- # @example
35
- # operation.execute(server)
36
- #
37
- # @param [ Mongo::Server ] server The server to send the operation to.
38
- #
39
- # @return [ Mongo::Operation::Insert::Result ] The operation result.
40
- #
41
- # @since 2.5.2
42
- def execute(server)
43
- result = Result.new(dispatch_message(server), @ids)
44
- process_result(result, server)
45
- end
46
-
47
33
  private
48
34
 
35
+ def get_result(server)
36
+ Result.new(dispatch_message(server), @ids)
37
+ end
38
+
49
39
  def selector(server)
50
40
  { insert: coll_name,
51
41
  documents: send(IDENTIFIER),
@@ -28,24 +28,12 @@ module Mongo
28
28
  include Executable
29
29
  include Idable
30
30
 
31
- # Execute the operation.
32
- #
33
- # @example
34
- # operation.execute(server)
35
- #
36
- # @param [ Mongo::Server ] server The server to send the operation to.
37
- #
38
- # @return [ Mongo::Operation::Insert::Result ] The operation result.
39
- #
40
- # @since 2.5.2
41
- def execute(server)
42
- result = Result.new(dispatch_message(server), @ids)
43
- process_result(result, server)
44
- result.validate!
45
- end
46
-
47
31
  private
48
32
 
33
+ def get_result(server)
34
+ Result.new(dispatch_message(server), @ids)
35
+ end
36
+
49
37
  def selector
50
38
  send(IDENTIFIER).first
51
39
  end
@@ -20,11 +20,15 @@ module Mongo
20
20
  # @since 2.5.2
21
21
  module Executable
22
22
 
23
+ include ResponseHandling
24
+
23
25
  def do_execute(server)
24
26
  unpin_maybe(session) do
25
27
  add_error_labels do
26
- get_result(server).tap do |result|
27
- process_result(result, server)
28
+ add_server_diagnostics(server) do
29
+ get_result(server).tap do |result|
30
+ process_result(result, server)
31
+ end
28
32
  end
29
33
  end
30
34
  end
@@ -32,7 +36,7 @@ module Mongo
32
36
 
33
37
  def execute(server)
34
38
  do_execute(server).tap do |result|
35
- validate_result(result)
39
+ validate_result(result, server)
36
40
  end
37
41
  end
38
42
 
@@ -0,0 +1,94 @@
1
+ # Copyright (C) 2019 MongoDB, Inc.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ module Mongo
16
+ module Operation
17
+
18
+ # Shared behavior of response handling for operations.
19
+ #
20
+ # @api private
21
+ module ResponseHandling
22
+
23
+ private
24
+
25
+ def validate_result(result, server)
26
+ unpin_maybe(session) do
27
+ add_error_labels do
28
+ add_server_diagnostics(server) do
29
+ result.validate!
30
+ end
31
+ end
32
+ end
33
+ end
34
+
35
+ # Adds error labels to exceptions raised in the yielded to block,
36
+ # which should perform MongoDB operations and raise Mongo::Errors on
37
+ # failure. This method handles network errors (Error::SocketError)
38
+ # and server-side errors (Error::OperationFailure); it does not
39
+ # handle server selection errors (Error::NoServerAvailable), for which
40
+ # labels are added in the server selection code.
41
+ def add_error_labels
42
+ begin
43
+ yield
44
+ rescue Mongo::Error::SocketError => e
45
+ if session && session.in_transaction? && !session.committing_transaction?
46
+ e.add_label('TransientTransactionError')
47
+ end
48
+ if session && session.committing_transaction?
49
+ e.add_label('UnknownTransactionCommitResult')
50
+ end
51
+ raise e
52
+ rescue Mongo::Error::OperationFailure => e
53
+ if session && session.committing_transaction?
54
+ if e.write_retryable? || e.wtimeout? || (e.write_concern_error? &&
55
+ !Session::UNLABELED_WRITE_CONCERN_CODES.include?(e.write_concern_error_code)
56
+ ) || e.max_time_ms_expired?
57
+ e.add_label('UnknownTransactionCommitResult')
58
+ end
59
+ end
60
+ raise e
61
+ end
62
+ end
63
+
64
+ # Unpins the session if the session is pinned and the yielded to block
65
+ # raises errors that are required to unpin the session.
66
+ #
67
+ # @note This method takes the session as an argument because this module
68
+ # is included in BulkWrite which does not store the session in the
69
+ # receiver (despite Specifiable doing so).
70
+ #
71
+ # @param [ Session | nil ] Session to consider.
72
+ def unpin_maybe(session)
73
+ yield
74
+ rescue Mongo::Error => e
75
+ if session
76
+ session.unpin_maybe(e)
77
+ end
78
+ raise
79
+ end
80
+
81
+ # Yields to the block and, if the block raises an exception, adds a note
82
+ # to the exception with the address of the specified server.
83
+ #
84
+ # This method is intended to add server address information to exceptions
85
+ # raised during execution of operations on servers.
86
+ def add_server_diagnostics(server)
87
+ yield
88
+ rescue Mongo::Error, Mongo::Error::AuthError => e
89
+ e.add_note("on #{server.address.seed}")
90
+ raise e
91
+ end
92
+ end
93
+ end
94
+ end
@@ -20,7 +20,6 @@ module Mongo
20
20
  #
21
21
  # @since 2.0.0
22
22
  module Specifiable
23
- include Unpinnable
24
23
 
25
24
  # The field for database name.
26
25
  #
@@ -565,45 +564,6 @@ module Mongo
565
564
  def acknowledged_write?
566
565
  write_concern.nil? || write_concern.acknowledged?
567
566
  end
568
-
569
- private
570
-
571
- def validate_result(result)
572
- unpin_maybe(session) do
573
- add_error_labels do
574
- result.validate!
575
- end
576
- end
577
- end
578
-
579
- # Adds error labels to exceptions raised in the yielded to block,
580
- # which should perform MongoDB operations and raise Mongo::Errors on
581
- # failure. This method handles network errors (Error::SocketError)
582
- # and server-side errors (Error::OperationFailure); it does not
583
- # handle server selection errors (Error::NoServerAvailable), for which
584
- # labels are added in the server selection code.
585
- def add_error_labels
586
- begin
587
- yield
588
- rescue Mongo::Error::SocketError => e
589
- if session && session.in_transaction? && !session.committing_transaction?
590
- e.add_label('TransientTransactionError')
591
- end
592
- if session && session.committing_transaction?
593
- e.add_label('UnknownTransactionCommitResult')
594
- end
595
- raise e
596
- rescue Mongo::Error::OperationFailure => e
597
- if session && session.committing_transaction?
598
- if e.write_retryable? || e.wtimeout? || (e.write_concern_error? &&
599
- !Session::UNLABELED_WRITE_CONCERN_CODES.include?(e.write_concern_error_code)
600
- ) || e.max_time_ms_expired?
601
- e.add_label('UnknownTransactionCommitResult')
602
- end
603
- end
604
- raise e
605
- end
606
- end
607
567
  end
608
568
  end
609
569
  end
@@ -20,6 +20,8 @@ module Mongo
20
20
  # @since 2.5.2
21
21
  module Write
22
22
 
23
+ include ResponseHandling
24
+
23
25
  # Execute the operation.
24
26
  #
25
27
  # @example
@@ -39,7 +41,7 @@ module Mongo
39
41
  else
40
42
  self.class::Command.new(spec).execute(server)
41
43
  end
42
- validate_result(result)
44
+ validate_result(result, server)
43
45
  end
44
46
 
45
47
  # Execute the bulk write operation.
@@ -206,19 +206,25 @@ module Mongo
206
206
  return legacy_write_with_retry(server, session, &block)
207
207
  end
208
208
 
209
+ txn_num = if session.in_transaction?
210
+ session.txn_num
211
+ else
212
+ session.next_txn_num
213
+ end
209
214
  begin
210
- txn_num = session.in_transaction? ? session.txn_num : session.next_txn_num
211
215
  yield(server, txn_num, false)
212
216
  rescue Error::SocketError, Error::SocketTimeoutError => e
217
+ e.add_note("attempt 1")
213
218
  if session.in_transaction? && !ending_transaction
214
- raise
219
+ raise e
215
220
  end
216
221
  retry_write(e, session, txn_num, &block)
217
222
  rescue Error::OperationFailure => e
223
+ e.add_note("attempt 1")
218
224
  if e.unsupported_retryable_write?
219
225
  raise_unsupported_error(e)
220
226
  elsif (session.in_transaction? && !ending_transaction) || !e.write_retryable?
221
- raise
227
+ raise e
222
228
  end
223
229
 
224
230
  retry_write(e, session, txn_num, &block)
@@ -274,16 +280,17 @@ module Mongo
274
280
  server ||= select_server(cluster, ServerSelector.primary, session)
275
281
  yield server
276
282
  rescue Error::OperationFailure => e
283
+ e.add_note("attempt #{attempt + 1}")
277
284
  server = nil
278
285
  if attempt > client.max_write_retries
279
- raise
286
+ raise e
280
287
  end
281
288
  if e.write_retryable? && !(session && session.in_transaction?)
282
289
  log_retry(e, message: 'Legacy write retry')
283
290
  cluster.scan!(false)
284
291
  retry
285
292
  else
286
- raise
293
+ raise e
287
294
  end
288
295
  end
289
296
  end
@@ -296,13 +303,15 @@ module Mongo
296
303
  begin
297
304
  yield server
298
305
  rescue Error::SocketError, Error::SocketTimeoutError => e
306
+ e.add_note("attempt #{attempt + 1}")
299
307
  if session.in_transaction?
300
- raise
308
+ raise e
301
309
  end
302
310
  retry_read(e, server_selector, session, &block)
303
311
  rescue Error::OperationFailure => e
312
+ e.add_note("attempt #{attempt + 1}")
304
313
  if session.in_transaction? || !e.write_retryable?
305
- raise
314
+ raise e
306
315
  end
307
316
  retry_read(e, server_selector, session, &block)
308
317
  end
@@ -315,23 +324,25 @@ module Mongo
315
324
  attempt += 1
316
325
  yield server
317
326
  rescue Error::SocketError, Error::SocketTimeoutError => e
327
+ e.add_note("attempt #{attempt + 1}")
318
328
  if attempt > client.max_read_retries || (session && session.in_transaction?)
319
- raise
329
+ raise e
320
330
  end
321
331
  log_retry(e, message: 'Legacy read retry')
322
332
  server = select_server(cluster, server_selector, session)
323
333
  retry
324
334
  rescue Error::OperationFailure => e
335
+ e.add_note("attempt #{attempt + 1}")
325
336
  if cluster.sharded? && e.retryable? && !(session && session.in_transaction?)
326
337
  if attempt > client.max_read_retries
327
- raise
338
+ raise e
328
339
  end
329
340
  log_retry(e, message: 'Legacy read retry')
330
341
  sleep(client.read_retry_interval)
331
342
  server = select_server(cluster, server_selector, session)
332
343
  retry
333
344
  else
334
- raise
345
+ raise e
335
346
  end
336
347
  end
337
348
  end
@@ -354,7 +365,8 @@ module Mongo
354
365
  def retry_read(original_error, server_selector, session, &block)
355
366
  begin
356
367
  server = select_server(cluster, server_selector, session)
357
- rescue
368
+ rescue => e
369
+ original_error.add_note("later retry failed: #{e.class}: #{e}")
358
370
  raise original_error
359
371
  end
360
372
 
@@ -363,11 +375,17 @@ module Mongo
363
375
  begin
364
376
  yield server, true
365
377
  rescue Error::SocketError, Error::SocketTimeoutError => e
378
+ e.add_note("attempt 2")
366
379
  raise e
367
380
  rescue Error::OperationFailure => e
368
- raise original_error unless e.write_retryable?
381
+ unless e.write_retryable?
382
+ original_error.add_note("later retry failed: #{e.class}: #{e}")
383
+ raise original_error
384
+ end
385
+ e.add_note("attempt 2")
369
386
  raise e
370
- rescue
387
+ rescue => e
388
+ original_error.add_note("later retry failed: #{e.class}: #{e}")
371
389
  raise original_error
372
390
  end
373
391
  end
@@ -379,15 +397,25 @@ module Mongo
379
397
  # a socket error or a not master error should have marked the respective
380
398
  # server unknown). Here we just need to wait for server selection.
381
399
  server = select_server(cluster, ServerSelector.primary, session)
382
- raise original_error unless (server.retry_writes? && txn_num)
400
+ unless server.retry_writes?
401
+ original_error.add_note('did not retry because server selected for retry does not supoprt retryable writes')
402
+ raise original_error
403
+ end
383
404
  log_retry(original_error, message: 'Write retry')
384
405
  yield(server, txn_num, true)
385
406
  rescue Error::SocketError, Error::SocketTimeoutError => e
407
+ e.add_note('attempt 2')
386
408
  raise e
387
409
  rescue Error::OperationFailure => e
388
- raise original_error unless e.write_retryable?
389
- raise e
390
- rescue
410
+ if e.write_retryable?
411
+ e.add_note('attempt 2')
412
+ raise e
413
+ else
414
+ original_error.add_note("later retry failed: #{e.class}: #{e}")
415
+ raise original_error
416
+ end
417
+ rescue => e
418
+ original_error.add_note("later retry failed: #{e.class}: #{e}")
391
419
  raise original_error
392
420
  end
393
421
 
@@ -17,5 +17,5 @@ module Mongo
17
17
  # The current version of the driver.
18
18
  #
19
19
  # @since 2.0.0
20
- VERSION = '2.10.0'.freeze
20
+ VERSION = '2.10.1'.freeze
21
21
  end
@@ -94,7 +94,7 @@ describe 'Change stream integration', retry: 4 do
94
94
  it 'watch raises error' do
95
95
  expect do
96
96
  authorized_collection.watch
97
- end.to raise_error(Mongo::Error::OperationFailure, "Failing command due to 'failCommand' failpoint (100)")
97
+ end.to raise_error(Mongo::Error::OperationFailure, /Failing command due to 'failCommand' failpoint \(100\)/)
98
98
  end
99
99
  end
100
100
 
@@ -243,7 +243,7 @@ describe 'Change stream integration', retry: 4 do
243
243
 
244
244
  expect do
245
245
  enum.next
246
- end.to raise_error(Mongo::Error::OperationFailure, "Failing command due to 'failCommand' failpoint (101)")
246
+ end.to raise_error(Mongo::Error::OperationFailure, /Failing command due to 'failCommand' failpoint \(101\)/)
247
247
  end
248
248
  end
249
249
  end
@@ -354,7 +354,7 @@ describe 'Change stream integration', retry: 4 do
354
354
 
355
355
  expect do
356
356
  enum.try_next
357
- end.to raise_error(Mongo::Error::OperationFailure, "Failing command due to 'failCommand' failpoint (101)")
357
+ end.to raise_error(Mongo::Error::OperationFailure, /Failing command due to 'failCommand' failpoint \(101\)/)
358
358
  end
359
359
  end
360
360
 
@@ -377,7 +377,7 @@ describe 'Change stream integration', retry: 4 do
377
377
 
378
378
  expect do
379
379
  enum.try_next
380
- end.to raise_error(Mongo::Error::OperationFailure, "Failing command due to 'failCommand' failpoint (101)")
380
+ end.to raise_error(Mongo::Error::OperationFailure, /Failing command due to 'failCommand' failpoint \(101\)/)
381
381
  end
382
382
  end
383
383
  end
@@ -107,7 +107,7 @@ describe 'Command monitoring' do
107
107
  subscriber.clear_events!
108
108
  expect do
109
109
  command.execute(server)
110
- end.to raise_error(Mongo::Error::OperationFailure, 'Not enough data-bearing nodes (100)')
110
+ end.to raise_error(Mongo::Error::OperationFailure, /Not enough data-bearing nodes \(100\)/)
111
111
 
112
112
  expect(subscriber.started_events.length).to eq(1)
113
113
  event = subscriber.started_events.first
@@ -409,7 +409,7 @@ describe 'Read preference' do
409
409
  res = collection.find({}, {session: session}.merge(find_options || {})).to_a.count
410
410
  expect(res).to eq(1)
411
411
  end
412
- end.to raise_error(Mongo::Error::InvalidTransactionOperation, "read preference in a transaction must be primary (requested: secondary)")
412
+ end.to raise_error(Mongo::Error::InvalidTransactionOperation, /read preference in a transaction must be primary \(requested: secondary\)/)
413
413
  end
414
414
  end
415
415
 
@@ -478,7 +478,7 @@ describe 'Read preference' do
478
478
  res = collection.find({}, {session: session}.merge(find_options || {})).to_a.count
479
479
  expect(res).to eq(1)
480
480
  end
481
- end.to raise_error(Mongo::Error::InvalidTransactionOperation, "read preference in a transaction must be primary (requested: secondary)")
481
+ end.to raise_error(Mongo::Error::InvalidTransactionOperation, /read preference in a transaction must be primary \(requested: secondary\)/)
482
482
  end
483
483
  end
484
484
  end
@@ -107,6 +107,18 @@ describe 'Retryable writes integration tests' do
107
107
  }.to raise_error(Mongo::Error::OperationFailure, /other error/)
108
108
  expect(expectation).to eq(unsuccessful_retry_value)
109
109
  end
110
+
111
+ it 'indicates server used for operation' do
112
+ expect {
113
+ operation
114
+ }.to raise_error(Mongo::Error::OperationFailure, /on #{ClusterConfig.instance.primary_address_str}/)
115
+ end
116
+
117
+ it 'indicates first attempt' do
118
+ expect {
119
+ operation
120
+ }.to raise_error(Mongo::Error::OperationFailure, /attempt 1/)
121
+ end
110
122
  end
111
123
  end
112
124
  end
@@ -169,16 +181,17 @@ describe 'Retryable writes integration tests' do
169
181
  end
170
182
 
171
183
  [
172
- Mongo::Error::SocketError,
173
- Mongo::Error::SocketTimeoutError,
174
- Mongo::Error::OperationFailure.new('not master'),
175
- Mongo::Error::OperationFailure.new('node is recovering'),
176
- ].each do |retryable_error|
184
+ [Mongo::Error::SocketError],
185
+ [Mongo::Error::SocketTimeoutError],
186
+ [Mongo::Error::OperationFailure, 'not master'],
187
+ [Mongo::Error::OperationFailure, 'node is recovering'],
188
+ ].each do |error_cls, error_msg|
189
+ # Note: actual exception instances must be different between tests
177
190
 
178
- context "when the first error is a #{retryable_error}" do
191
+ context "when the first error is a #{error_cls}/#{error_msg}" do
179
192
 
180
193
  let(:error) do
181
- retryable_error
194
+ error_cls.new(error_msg)
182
195
  end
183
196
 
184
197
  before do
@@ -197,12 +210,24 @@ describe 'Retryable writes integration tests' do
197
210
  Mongo::Error::SocketError
198
211
  end
199
212
 
200
- it 'does not retry writes and raises the second error' do
213
+ it 'raises the second error' do
201
214
  expect {
202
215
  operation
203
216
  }.to raise_error(second_error)
204
217
  expect(expectation).to eq(unsuccessful_retry_value)
205
218
  end
219
+
220
+ it 'indicates server used for operation' do
221
+ expect {
222
+ operation
223
+ }.to raise_error(Mongo::Error, /on #{ClusterConfig.instance.primary_address_str}/)
224
+ end
225
+
226
+ it 'indicates second attempt' do
227
+ expect {
228
+ operation
229
+ }.to raise_error(Mongo::Error, /attempt 2/)
230
+ end
206
231
  end
207
232
 
208
233
  context 'when the second error is a SocketTimeoutError' do
@@ -211,7 +236,7 @@ describe 'Retryable writes integration tests' do
211
236
  Mongo::Error::SocketTimeoutError
212
237
  end
213
238
 
214
- it 'does not retry writes and raises the second error' do
239
+ it 'raises the second error' do
215
240
  expect {
216
241
  operation
217
242
  }.to raise_error(second_error)
@@ -225,7 +250,7 @@ describe 'Retryable writes integration tests' do
225
250
  Mongo::Error::OperationFailure.new('not master')
226
251
  end
227
252
 
228
- it 'does not retry writes and raises the second error' do
253
+ it 'raises the second error' do
229
254
  expect {
230
255
  operation
231
256
  }.to raise_error(second_error)
@@ -253,12 +278,30 @@ describe 'Retryable writes integration tests' do
253
278
  StandardError
254
279
  end
255
280
 
256
- it 'does not retry writes and raises the first error' do
281
+ it 'raises the first error' do
257
282
  expect {
258
283
  operation
259
284
  }.to raise_error(error)
260
285
  expect(expectation).to eq(unsuccessful_retry_value)
261
286
  end
287
+
288
+ it 'indicates server used for operation' do
289
+ expect {
290
+ operation
291
+ }.to raise_error(Mongo::Error, /on #{ClusterConfig.instance.primary_address_str}/)
292
+ end
293
+
294
+ it 'indicates first attempt' do
295
+ expect {
296
+ operation
297
+ }.to raise_error(Mongo::Error, /attempt 1/)
298
+ end
299
+
300
+ it 'indicates retry was performed' do
301
+ expect {
302
+ operation
303
+ }.to raise_error(Mongo::Error, /later retry failed: StandardError/)
304
+ end
262
305
  end
263
306
  end
264
307
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mongo
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.10.0
4
+ version: 2.10.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tyler Brock
@@ -31,7 +31,7 @@ cert_chain:
31
31
  bMYVwXXhV8czdzgkQB/ZPWHSbEWXnmkze1mzvqWBCPOVXYrcnL9cnEl/RoxtS1hr
32
32
  Db6Ac6mCUSYfYHBWpWqxjc45n70i5Xi1
33
33
  -----END CERTIFICATE-----
34
- date: 2019-08-13 00:00:00.000000000 Z
34
+ date: 2019-08-29 00:00:00.000000000 Z
35
35
  dependencies:
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: bson
@@ -140,6 +140,7 @@ files:
140
140
  - lib/mongo/database/view.rb
141
141
  - lib/mongo/dbref.rb
142
142
  - lib/mongo/error.rb
143
+ - lib/mongo/error/auth_error.rb
143
144
  - lib/mongo/error/bulk_write_error.rb
144
145
  - lib/mongo/error/change_stream_resumable.rb
145
146
  - lib/mongo/error/closed_stream.rb
@@ -180,6 +181,7 @@ files:
180
181
  - lib/mongo/error/need_primary_server.rb
181
182
  - lib/mongo/error/no_server_available.rb
182
183
  - lib/mongo/error/no_srv_records.rb
184
+ - lib/mongo/error/notable.rb
183
185
  - lib/mongo/error/operation_failure.rb
184
186
  - lib/mongo/error/parser.rb
185
187
  - lib/mongo/error/pool_closed_error.rb
@@ -355,11 +357,11 @@ files:
355
357
  - lib/mongo/operation/shared/polymorphic_lookup.rb
356
358
  - lib/mongo/operation/shared/polymorphic_result.rb
357
359
  - lib/mongo/operation/shared/read_preference_supported.rb
360
+ - lib/mongo/operation/shared/response_handling.rb
358
361
  - lib/mongo/operation/shared/result/aggregatable.rb
359
362
  - lib/mongo/operation/shared/result/use_legacy_error_parser.rb
360
363
  - lib/mongo/operation/shared/sessions_supported.rb
361
364
  - lib/mongo/operation/shared/specifiable.rb
362
- - lib/mongo/operation/shared/unpinnable.rb
363
365
  - lib/mongo/operation/shared/write.rb
364
366
  - lib/mongo/operation/shared/write_concern_supported.rb
365
367
  - lib/mongo/operation/update.rb
metadata.gz.sig CHANGED
Binary file
@@ -1,39 +0,0 @@
1
- # Copyright (C) 2014-2019 MongoDB, Inc.
2
- #
3
- # Licensed under the Apache License, Version 2.0 (the "License");
4
- # you may not use this file except in compliance with the License.
5
- # You may obtain a copy of the License at
6
- #
7
- # http://www.apache.org/licenses/LICENSE-2.0
8
- #
9
- # Unless required by applicable law or agreed to in writing, software
10
- # distributed under the License is distributed on an "AS IS" BASIS,
11
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
- # See the License for the specific language governing permissions and
13
- # limitations under the License.
14
-
15
- module Mongo
16
- module Operation
17
- module Unpinnable
18
-
19
- private
20
-
21
- # Unpins the session if the session is pinned and the yielded to block
22
- # raises errors that are required to unpin the session.
23
- #
24
- # @note This method takes the session as an argument because Unpinnable
25
- # is included in BulkWrite which does not store the session in the
26
- # receiver (despite Specifiable doing so).
27
- #
28
- # @param [ Session | nil ] Session to consider.
29
- def unpin_maybe(session)
30
- yield
31
- rescue Mongo::Error => e
32
- if session
33
- session.unpin_maybe(e)
34
- end
35
- raise
36
- end
37
- end
38
- end
39
- end