lib/mongo/retryable.rb in mongo-2.12.4 vs lib/mongo/retryable.rb in mongo-2.13.0.beta1
- old
+ new
@@ -1,6 +1,6 @@
-# Copyright (C) 2015-2019 MongoDB, Inc.
+# Copyright (C) 2015-2020 MongoDB Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
@@ -219,20 +219,20 @@
begin
yield(server, txn_num, false)
rescue Error::SocketError, Error::SocketTimeoutError => e
e.add_note('modern retry')
e.add_note("attempt 1")
- if session.in_transaction? && !ending_transaction
+ if !e.label?('RetryableWriteError')
raise e
end
retry_write(e, session, txn_num, &block)
rescue Error::OperationFailure => e
e.add_note('modern retry')
e.add_note("attempt 1")
if e.unsupported_retryable_write?
raise_unsupported_error(e)
- elsif (session.in_transaction? && !ending_transaction) || !e.write_retryable?
+ elsif !e.label?('RetryableWriteError')
raise e
end
retry_write(e, session, txn_num, &block)
end
@@ -296,11 +296,11 @@
e.add_note("attempt #{attempt}")
server = nil
if attempt > client.max_write_retries
raise e
end
- if e.write_retryable? && !(session && session.in_transaction?)
+ if e.label?('RetryableWriteError')
log_retry(e, message: 'Legacy write retry')
cluster.scan!(false)
retry
else
raise e
@@ -379,13 +379,15 @@
end
def retry_read(original_error, server_selector, session, &block)
begin
server = select_server(cluster, server_selector, session)
- rescue => e
+ rescue Error, Error::AuthError => e
original_error.add_note("later retry failed: #{e.class}: #{e}")
- raise original_error
+
+ # See the corresponding note below in retry_write.
+ raise Error::RaiseOriginalError
end
log_retry(original_error, message: 'Read retry')
begin
@@ -400,15 +402,17 @@
original_error.add_note("later retry failed: #{e.class}: #{e}")
raise original_error
end
e.add_note("attempt 2")
raise e
- rescue => e
+ rescue Error, Error::AuthError => e
e.add_note('modern retry')
original_error.add_note("later retry failed: #{e.class}: #{e}")
raise original_error
end
+ rescue Error::RaiseOriginalError
+ raise original_error
end
def retry_write(original_error, session, txn_num, &block)
# We do not request a scan of the cluster here, because error handling
# for the error which triggered the retry should have updated the
@@ -418,30 +422,39 @@
server = select_server(cluster, ServerSelector.primary, session)
unless server.retry_writes?
# Do not need to add "modern retry" here, it should already be on
# the first exception.
original_error.add_note('did not retry because server selected for retry does not supoprt retryable writes')
- raise original_error
+
+ # When we want to raise the original error, we must not run the
+ # rescue blocks below that add diagnostics because the diagnostics
+ # added would either be rendundant (e.g. modern retry note) or wrong
+ # (e.g. "attempt 2", we are raising the exception produced in the
+ # first attempt and haven't attempted the second time). Use the
+ # special marker class to bypass the ordinarily applicable rescues.
+ raise Error::RaiseOriginalError
end
log_retry(original_error, message: 'Write retry')
yield(server, txn_num, true)
rescue Error::SocketError, Error::SocketTimeoutError => e
e.add_note('modern retry')
e.add_note('attempt 2')
raise e
rescue Error::OperationFailure => e
e.add_note('modern retry')
- if e.write_retryable?
+ if e.label?('RetryableWriteError')
e.add_note('attempt 2')
raise e
else
original_error.add_note("later retry failed: #{e.class}: #{e}")
raise original_error
end
- rescue => e
+ rescue Error, Error::AuthError => e
# Do not need to add "modern retry" here, it should already be on
# the first exception.
original_error.add_note("later retry failed: #{e.class}: #{e}")
+ raise original_error
+ rescue Error::RaiseOriginalError
raise original_error
end
# This is a separate method to make it possible for the test suite to
# assert that server selection is performed during retry attempts.