123456789_123456789_123456789_123456789_123456789_

Module: Mongo::Operation::Executable Private

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

Overview

Shared executable behavior of operations.

Since:

  • 2.5.2

Constant Summary

Instance Attribute Summary

Instance Method Summary

ResponseHandling - Included

#add_error_labels

Adds error labels to exceptions raised in the yielded to block, which should perform MongoDB operations and raise Mongo::Errors on failure.

#add_server_diagnostics

Yields to the block and, if the block raises an exception, adds a note to the exception with the address of the specified server.

#maybe_add_retryable_write_error_label!

A method that will add the RetryableWriteError label to an error if any of the following conditions are true:

#unpin_maybe

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

#validate_result

Instance Attribute Details

#contextOperation::Context | nil (rw)

Returns:

Since:

  • 2.5.2

[ GitHub ]

  
# File 'lib/mongo/operation/shared/executable.rb', line 33

attr_accessor :context

Instance Method Details

#build_message(connection, context) (private)

Parameters:

Since:

  • 2.5.2

[ GitHub ]

  
# File 'lib/mongo/operation/shared/executable.rb', line 121

def build_message(connection, context)
  msg = message(connection)
  if server_api = context.server_api
    msg = msg.maybe_add_server_api(server_api)
  end
  msg
end

#check_for_network_error (private)

Since:

  • 2.5.2

[ GitHub ]

  
# File 'lib/mongo/operation/shared/executable.rb', line 168

def check_for_network_error
  yield
rescue *NETWORK_ERRORS
  session&.dirty!
  raise
end

#dispatch_message(connection, context, options = {}) (private)

Returns a ::Mongo::Protocol::Message or nil as reply.

Since:

  • 2.5.2

[ GitHub ]

  
# File 'lib/mongo/operation/shared/executable.rb', line 111

def dispatch_message(connection, context, options = {})
  message = build_message(connection, context)
  message = message.maybe_encrypt(connection, context)
  reply = connection.dispatch([ message ], context, options)
  [reply, connection.description, connection.global_id]
end

#do_execute(connection, context, options = {})

Since:

  • 2.5.2

[ GitHub ]

  
# File 'lib/mongo/operation/shared/executable.rb', line 35

def do_execute(connection, context, options = {})
  # Save the context on the instance, to avoid having to pass it as a
  # parameter to every single method. There are many legacy methods that
  # still accept it as a parameter, which are left as-is for now to
  # minimize the impact of this change. Moving forward, it may be
  # reasonable to refactor things so this saved reference is used instead.
  @context = context

  session&.materialize_if_needed
  unpin_maybe(session, connection) do
    add_error_labels(connection, context) do
      check_for_network_error do
        add_server_diagnostics(connection) do
          get_result(connection, context, options).tap do |result|
            if session
              if session.in_transaction? &&
                connection.description.load_balancer?
              then
                if session.pinned_connection_global_id
                  unless session.pinned_connection_global_id == connection.global_id
                    raise(
                      Error::InternalDriverError,
                      "Expected operation to use connection #{session.pinned_connection_global_id} but it used #{connection.global_id}"
                    )
                  end
                else
                  session.pin_to_connection(connection.global_id)
                  connection.pin
                end
              end

              if session.snapshot? && !session.snapshot_timestamp
                session.snapshot_timestamp = result.snapshot_timestamp
              end
            end

            if result.has_cursor_id? &&
              connection.description.load_balancer?
            then
              if result.cursor_id == 0
                connection.unpin
              else
                connection.pin
              end
            end
            process_result(result, connection)
          end
        end
      end
    end
  end
end

#execute(connection, context:, options: {})

Since:

  • 2.5.2

[ GitHub ]

  
# File 'lib/mongo/operation/shared/executable.rb', line 88

def execute(connection, context:, options: {})
  if Lint.enabled?
    unless connection.is_a?(Mongo::Server::Connection)
      raise Error::LintError, "Connection argument is of wrong type: #{connection}"
    end
  end

  do_execute(connection, context, options).tap do |result|
    validate_result(result, connection, context)
  end
end

#get_result(connection, context, options = {}) (private)

Since:

  • 2.5.2

[ GitHub ]

  
# File 'lib/mongo/operation/shared/executable.rb', line 106

def get_result(connection, context, options = {})
  result_class.new(*dispatch_message(connection, context, options), context: context, connection: connection)
end

#process_result(result, connection) (private)

Since:

  • 2.5.2

[ GitHub ]

  
# File 'lib/mongo/operation/shared/executable.rb', line 129

def process_result(result, connection)
  connection.server.update_cluster_time(result)

  process_result_for_sdam(result, connection)

  if session
    session.process(result)
  end

  result
end

#process_result_for_sdam(result, connection) (private)

Since:

  • 2.5.2

[ GitHub ]

  
# File 'lib/mongo/operation/shared/executable.rb', line 141

def process_result_for_sdam(result, connection)
  if (result.not_master? || result.node_recovering?) &&
    connection.generation >= connection.server.pool.generation(service_id: connection.service_id)
  then
    if result.node_shutting_down?
      keep_pool = false
    else
      # Max wire version needs to be examined while the server is known
      keep_pool = connection.description.server_version_gte?('4.2')
    end

    connection.server.unknown!(
      keep_connection_pool: keep_pool,
      generation: connection.generation,
      service_id: connection.service_id,
      topology_version: result.topology_version,
    )

    connection.server.scan_semaphore.signal
  end
end

#result_class (private)

Since:

  • 2.5.2

[ GitHub ]

  
# File 'lib/mongo/operation/shared/executable.rb', line 102

def result_class
  Result
end