module Mongo::Operation::ResponseHandling
Shared behavior of response handling for operations.
@api private
Private Instance Methods
Adds error labels to exceptions raised in the yielded to block, which should perform MongoDB operations and raise Mongo::Errors on failure. This method handles network errors (Error::SocketError
) and server-side errors (Error::OperationFailure
); it does not handle server selection errors (Error::NoServerAvailable
), for which labels are added in the server selection code.
# File lib/mongo/operation/shared/response_handling.rb, line 41 def add_error_labels(client, connection, session) begin yield rescue Mongo::Error::SocketError => e if session && session.in_transaction? && !session.committing_transaction? e.add_label('TransientTransactionError') end if session && session.committing_transaction? e.add_label('UnknownTransactionCommitResult') end maybe_add_retryable_write_error_label!(e, connection, client, session) raise e rescue Mongo::Error::SocketTimeoutError => e maybe_add_retryable_write_error_label!(e, connection, client, session) raise e rescue Mongo::Error::OperationFailure => e if session && session.committing_transaction? if e.write_retryable? || e.wtimeout? || (e.write_concern_error? && !Session::UNLABELED_WRITE_CONCERN_CODES.include?(e.write_concern_error_code) ) || e.max_time_ms_expired? e.add_label('UnknownTransactionCommitResult') end end maybe_add_retryable_write_error_label!(e, connection, client, session) raise e end end
Yields to the block and, if the block raises an exception, adds a note to the exception with the address of the specified server.
This method is intended to add server address information to exceptions raised during execution of operations on servers.
# File lib/mongo/operation/shared/response_handling.rb, line 95 def add_server_diagnostics(connection) yield rescue Error::SocketError, Error::SocketTimeoutError # Diagnostics should have already been added by the connection code, # do not add them again. raise rescue Error, Error::AuthError => e e.add_note("on #{connection.address.seed}") e.generation = connection.generation raise e end
A method that will add the RetryableWriteError label to an error if any of the following conditions are true:
The error meets the criteria for a retryable error (i.e. has one
of the retryable error codes or error messages)
AND the server does not support adding the RetryableWriteError label OR
the error is a network error (i.e. the driver must add the label)
AND the error occured during a commitTransaction or abortTransaction
OR the error occured during a write outside of a transaction on a client that has retry writes enabled.
If these conditions are met, the original error will be mutated. If they’re not met, the error will not be changed.
@param [ Mongo::Error
] error The error to which to add the label. @param [ Mongo::Server::Connection
] connection The connection on which
the operation is performed.
@param [ Mongo::Client
| nil ] client The client that is performing
the operation.
@param [ Mongo::Session
] session The operation’s session.
@note The client argument is optional because some operations, such as
end_session, do not pass the client as an argument to the execute method.
# File lib/mongo/operation/shared/response_handling.rb, line 135 def maybe_add_retryable_write_error_label!(error, connection, client, session) in_transaction = session && session.in_transaction? committing_transaction = in_transaction && session.committing_transaction? aborting_transaction = in_transaction && session.aborting_transaction? modern_retry_writes = client && client.options[:retry_writes] legacy_retry_writes = client && !client.options[:retry_writes] && client.max_write_retries > 0 # An operation is retryable if it meets one of the following criteria: # - It is a commitTransaction or abortTransaction # - It does not occur during a transaction and the client has enabled # modern or legacy writes # # Note: any write operation within a transaction (excepting commit and # abort is NOT a retryable operation) retryable_operation = committing_transaction || aborting_transaction || (!in_transaction && (modern_retry_writes || legacy_retry_writes)) # An operation should add the RetryableWriteError label if one of the # following conditions is met: # - The server does not support adding the RetryableWriteError label # - The error is a network error should_add_error_label = !connection.description.features.retryable_write_error_label_enabled? || error.write_concern_error_label?('RetryableWriteError') || error.is_a?(Mongo::Error::SocketError) || error.is_a?(Mongo::Error::SocketTimeoutError) if retryable_operation && should_add_error_label && error.write_retryable? error.add_label('RetryableWriteError') end end
Unpins the session if the session is pinned and the yielded to block raises errors that are required to unpin the session.
@note This method takes the session as an argument because this module
is included in BulkWrite which does not store the session in the receiver (despite Specifiable doing so).
@param [ Session
| nil ] session Session
to consider.
# File lib/mongo/operation/shared/response_handling.rb, line 81 def unpin_maybe(session) yield rescue Mongo::Error => e if session session.unpin_maybe(e) end raise end
# File lib/mongo/operation/shared/response_handling.rb, line 25 def validate_result(result, client, connection) unpin_maybe(session) do add_error_labels(client, connection, session) do add_server_diagnostics(connection) do result.validate! end end end end