123456789_123456789_123456789_123456789_123456789_

Module: Mongo::Operation::ResponseHandling Private

Do not use. This module is for internal use only.

Overview

Shared behavior of response handling for operations.

Instance Method Summary

Instance Method Details

#add_error_labels(connection, context) (private)

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.

Parameters:

[ GitHub ]

  
# File 'lib/mongo/operation/shared/response_handling.rb', line 52

def add_error_labels(connection, context)
  yield
rescue Mongo::Error::SocketError => e
  if context.in_transaction? && !context.committing_transaction?
    e.add_label('TransientTransactionError')
  end
  if context.committing_transaction?
    e.add_label('UnknownTransactionCommitResult')
  end

  maybe_add_retryable_write_error_label!(e, connection, context)

  raise e
rescue Mongo::Error::SocketTimeoutError => e
  maybe_add_retryable_write_error_label!(e, connection, context)
  raise e
rescue Mongo::Error::OperationFailure => e
  if context.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, context)

  raise e
end

#add_server_diagnostics(connection) (private)

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.

[ GitHub ]

  
# File 'lib/mongo/operation/shared/response_handling.rb', line 105

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
  e.service_id = connection.service_id
  raise e
end

#maybe_add_retryable_write_error_label!(error, connection, context) (private)

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.

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.

Parameters:

[ GitHub ]

  
# File 'lib/mongo/operation/shared/response_handling.rb', line 144

def maybe_add_retryable_write_error_label!(error, connection, context)
  # 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 = context.committing_transaction? ||
    context.aborting_transaction? ||
    !context.in_transaction? && context.any_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

#unpin_maybe(session, connection) (private)

Note:

This method takes the session as an argument because this module is included in ::Mongo::BulkWrite which does not store the session in the receiver (despite Specifiable doing so).

Unpins the session and/or the connection if the yielded to block raises errors that are required to unpin the session and the connection.

Parameters:

[ GitHub ]

  
# File 'lib/mongo/operation/shared/response_handling.rb', line 91

def unpin_maybe(session, connection)
  yield
rescue Mongo::Error => e
  if session
    session.unpin_maybe(e, connection)
  end
  raise
end

#validate_result(result, connection, context) (private)

Parameters:

[ GitHub ]

  
# File 'lib/mongo/operation/shared/response_handling.rb', line 32

def validate_result(result, connection, context)
  unpin_maybe(context.session, connection) do
    add_error_labels(connection, context) do
      add_server_diagnostics(connection) do
        result.validate!
      end
    end
  end
end