lib/mongo/retryable.rb
# Implements write retrying functionality by yielding to the passed
# block one or more times.
#
# If the session is provided (hence, the deployment supports sessions),
# and modern retry writes are enabled on the client, the modern retry
# logic is invoked. Otherwise the legacy retry logic is invoked.
#
# If ending_transaction parameter is true, indicating that a transaction
# is being committed or aborted, the operation is executed exactly once.
# Note that, since transactions require sessions, this method will raise
# ArgumentError if ending_transaction is true and session is nil.
#
# @api private
#
# @example Execute the write.
#   write_with_retry do
#     ...
#   end
#
# @note This only retries operations on not master failures, since it is
#   the only case we can be sure a partial write did not already occur.
#
# @param [ nil | Session ] session Optional session to use with the operation.
# @param [ nil | Hash | WriteConcern::Base ] write_concern The write concern.
# @param [ true | false ] ending_transaction True if the write operation is abortTransaction or
#   commitTransaction, false otherwise.
# @param [ Proc ] block The block to execute.
#
# @yieldparam [ Server ] server The server to which the write should be sent.
# @yieldparam [ Integer ] txn_num Transaction number (NOT the ACID kind).
#
# @return [ Result ] The result of the operation.
#
# @since 2.1.0
Implements write retrying functionality by yielding to the passed
block one or more times.

If the session is provided (hence, the deployment supports sessions),
and modern retry writes are enabled on the client, the modern retry
logic is invoked. Otherwise the legacy retry logic is invoked.

If ending_transaction parameter is true, indicating that a transaction
is being committed or aborted, the operation is executed exactly once.
Note that, since transactions require sessions, this method will raise
ArgumentError if ending_transaction is true and session is nil.
Implements write retrying functionality by yielding to the passed block one or more times . If the session is provided ( hence the deployment supports sessions ) and modern retry writes are enabled on the client the modern retry logic is invoked . Otherwise the legacy retry logic is invoked . If ending_transaction parameter is true indicating that a transaction is being committed or aborted the operation is executed exactly once . Note that since transactions require sessions this method will raise ArgumentError if ending_transaction is true and session is nil .
def write_with_retry(session, write_concern, ending_transaction = false, &block)
      if ending_transaction && !session
        raise ArgumentError, 'Cannot end a transaction without a session'
      end
      unless ending_transaction || retry_write_allowed?(session, write_concern)
        return legacy_write_with_retry(nil, session, &block)
      end
      server = select_server(cluster, ServerSelector.primary, session)
      unless ending_transaction || server.retry_writes?
        return legacy_write_with_retry(server, session, &block)
      end
      txn_num = if session.in_transaction?
        session.txn_num
      else
        session.next_txn_num
      end
      begin
        yield(server, txn_num, false)
      rescue Error::SocketError, Error::SocketTimeoutError => e
        e.add_note('modern retry')
        e.add_note("attempt 1")
        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 !e.label?('RetryableWriteError')
          raise e
        end
        retry_write(e, session, txn_num, &block)
      end
    end
def write_with_retry ( session , write_concern , ending_transaction = false , & block ) if ending_transaction && ! session raise ArgumentError , 'Cannot end a transaction without a session' end unless ending_transaction || retry_write_allowed? ( session , write_concern ) return legacy_write_with_retry ( nil , session , & block ) end server = select_server ( cluster , ServerSelector . primary , session ) unless ending_transaction || server . retry_writes? return legacy_write_with_retry ( server , session , & block ) end txn_num = if session . in_transaction? session . txn_num else session . next_txn_num end begin yield ( server , txn_num , false ) rescue Error :: SocketError , Error :: SocketTimeoutError => e e . add_note ( 'modern retry' ) e . add_note ( "attempt 1" ) 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 ! e . label? ( 'RetryableWriteError' ) raise e end retry_write ( e , session , txn_num , & block ) end end
Implements write retrying functionality by yielding to the passed
block one or more times.
Implements write retrying functionality by yielding to the passed block one or more times .
# If we are here, session is not nil. A session being nil would have # failed retry_write_allowed? check.
The result of the operation.
The result of the operation .
 Result 
session
write_concern
ending_transaction
block
txn_num Transaction number (NOT the ACID kind).
txn_num Transaction number ( NOT the ACID kind ) .
api
None
example
Execute the write. write_with_retry do ... end
Execute the write . write_with_retry do ... end
note
This only retries operations on not master failures, since it is the only case we can be sure a partial write did not already occur.
This only retries operations on not master failures since it is the only case we can be sure a partial write did not already occur .
since
None