123456789_123456789_123456789_123456789_123456789_

Class: Mongo::Server::Connection

Relationships & Source Files
Super Chains via Extension / Inclusion / Inheritance
Class Chain:
self, Forwardable, ConnectionBase, Forwardable, ConnectionCommon
Instance Chain:
Inherits: Mongo::Server::ConnectionBase
Defined in: lib/mongo/server/connection.rb

Overview

This class models the socket connections for servers and their behavior.

Since:

  • 2.0.0

Constant Summary

ConnectionCommon - Inherited

HELLO_DOC, LEGACY_HELLO_DOC

::Mongo::Loggable - Included

PREFIX

ConnectionBase - Inherited

DEFAULT_MAX_BSON_OBJECT_SIZE, MAX_BSON_COMMAND_OVERHEAD, REDUCED_MAX_BSON_SIZE

Class Method Summary

Instance Attribute Summary

ConnectionBase - Inherited

#description

Returns the server description for this connection, derived from the hello response for the handshake performed on this connection.

#options, #server

::Mongo::Monitoring::Publishable - Included

ConnectionCommon - Inherited

#compressor

The compressor negotiated during the handshake for this connection, if any.

#connected?

Determine if the connection is currently connected.

#pid, #socket

Instance Method Summary

::Mongo::Retryable - Included

#read_worker

Returns the read worker for handling retryable reads.

#select_server

This is a separate method to make it possible for the test suite to assert that server selection is performed during retry attempts.

#with_overload_retry

Wraps an operation with overload retry logic.

#write_worker

Returns the write worker for handling retryable writes.

#deprioritize_server?

Whether the failed server should be deprioritized during server selection for a retry attempt.

ConnectionBase - Inherited

#app_metadata,
#dispatch

Dispatch a single message to the connection.

#generation

Connection pool generation from which this connection was created.

#service_id,
#check_timeout!

If timeoutMS is set for the operation context, checks whether there is enough time left to send the corresponding message to the server (remaining timeout is bigger than minimum round trip time for the server).

#deliver, #serialize

::Mongo::Monitoring::Publishable - Included

::Mongo::Loggable - Included

#log_debug

Convenience method to log debug messages with the standard prefix.

#log_error

Convenience method to log error messages with the standard prefix.

#log_fatal

Convenience method to log fatal messages with the standard prefix.

#log_info

Convenience method to log info messages with the standard prefix.

#log_warn

Convenience method to log warn messages with the standard prefix.

#logger

Get the logger instance.

#_mongo_log_prefix, #format_message

ConnectionCommon - Inherited

#handshake_command

Build a command that should be used for connection handshake.

#handshake_document

Build a document that should be used for connection handshake.

#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.

#ensure_connected, #set_compressor!, #ssl_options

Constructor Details

.new(server, options = {}) ⇒ Connection

Note:

Connection must never be directly instantiated outside of a ::Mongo::Server.

Creates a new connection object to the specified target address with the specified options.

The constructor does not perform any I/O (and thus does not create sockets, handshakes nor authenticates); call connect! method on the connection object to create the network connection.

Examples:

Create the connection.

Connection.new(server)

Parameters:

  • server (Mongo::Server)

    The server the connection is for.

  • options (Hash) (defaults to: {})

    The connection options.

Options Hash (options):

  • :pipe (IO)

    The file descriptor for the read end of the pipe to listen on during the select system call when reading from the socket.

  • :generation (Integer)

    The generation of this connection. The generation should only be specified in this option when not in load-balancing mode, and it should be the generation of the connection pool when the connection is created. In load-balancing mode, the generation is set on the connection after the handshake completes.

  • :server_api (Hash)

    The requested server API version. This hash can have the following items:

    • :version -- string
    • :strict -- boolean
    • :deprecation_errors -- boolean

Since:

  • 2.0.0

[ GitHub ]

  
# File 'lib/mongo/server/connection.rb', line 90

def initialize(server, options = {})
  super()
  if server.load_balancer? && options[:generation]
    raise ArgumentError, 'Generation cannot be set when server is a load balancer'
  end

  @id = server.next_connection_id
  @global_id = self.class.next_id
  @monitoring = server.monitoring
  @options = options.freeze
  @server = server
  @socket = nil
  @last_checkin = nil
  @auth_mechanism = nil
  @pid = Process.pid
  @pin_reasons = Set.new

  publish_cmap_event(
    Monitoring::Event::Cmap::ConnectionCreated.new(address, id)
  )
end

Instance Attribute Details

#closed?true | false (readonly)

Whether the connection was closed.

Closed connections should no longer be used. Instead obtain a new connection from the connection pool.

Returns:

  • (true | false)

    Whether connection was closed.

Since:

  • 2.9.0

[ GitHub ]

  
# File 'lib/mongo/server/connection.rb', line 153

def closed?
  !!@closed
end

#connected?true | false (readonly)

Whether the connection was connected and was not interrupted, closed, or had an error raised.

Returns:

  • (true | false)

    if the connection was connected.

Since:

  • 2.0.0

[ GitHub ]

  
# File 'lib/mongo/server/connection.rb', line 141

def connected?
  !closed? && !error? && !interrupted? && !!@socket
end

#error?Boolean (readonly)

Since:

  • 2.0.0

[ GitHub ]

  
# File 'lib/mongo/server/connection.rb', line 173

def error?
  !!@error
end

#global_idInteger (readonly)

across all connections.

Returns:

  • (Integer)

    The global ID for the connection. This will be unique

Since:

  • 2.0.0

[ GitHub ]

  
# File 'lib/mongo/server/connection.rb', line 125

attr_reader :global_id

#idInteger (readonly)

across connections to the same server object.

Returns:

  • (Integer)

    The ID for the connection. This will be unique

Since:

  • 2.9.0

[ GitHub ]

  
# File 'lib/mongo/server/connection.rb', line 121

attr_reader :id

#interrupted?true | false (readonly)

Whether the connection was interrupted.

Interrupted connections were already removed from the pool and should not be checked back into the pool.

Returns:

  • (true | false)

    Whether connection was interrupted.

Since:

  • 2.0.0

[ GitHub ]

  
# File 'lib/mongo/server/connection.rb', line 163

def interrupted?
  !!@interrupted
end

#last_checkinTime (readonly)

Returns:

  • (Time)

    The last time the connection was checked back into a pool.

Since:

  • 2.5.0

[ GitHub ]

  
# File 'lib/mongo/server/connection.rb', line 115

attr_reader :last_checkin

#pinned?Boolean (readonly)

Whether the connection is used by a transaction or cursor operations.

Pinned connections should not be disconnected and removed from a connection pool if they are idle or stale.

@return [ true | false ] Whether connection is pinned.

Since:

  • 2.0.0

[ GitHub ]

  
# File 'lib/mongo/server/connection.rb', line 185

def pinned?
  !@pin_reasons.empty?
end

Instance Method Details

#connect!(context = nil) ⇒ true

Note:

This method mutates the connection object by setting a socket if one previously did not exist.

Establishes a network connection to the target address.

If the connection is already established, this method does nothing.

Examples:

Connect to the host.

connection.connect!

Returns:

  • (true)

    If the connection succeeded.

Since:

  • 2.0.0

[ GitHub ]

  
# File 'lib/mongo/server/connection.rb', line 229

def connect!(context = nil)
  raise_if_closed!

  unless @socket
    @socket = create_socket(context)
    @description, @compressor = do_connect

    if server.load_balancer?
      if Lint.enabled? && !service_id
        raise Error::InternalDriverError,
              'The connection is to a load balancer and it must have service_id set here, but does not'
      end
      @generation = connection_pool.generation_manager.generation(service_id: service_id)
    end

    publish_cmap_event(
      Monitoring::Event::Cmap::ConnectionReady.new(address, id)
    )

    @close_event_published = false
  end
  true
end

#connection_pool

The connection pool from which this connection was created. May be nil.

Since:

  • 2.0.0

[ GitHub ]

  
# File 'lib/mongo/server/connection.rb', line 133

def connection_pool
  options[:connection_pool]
end

#create_socket(context = nil) ⇒ Socket (private)

Creates the socket. The method is separate from do_connect, so that pending connections can be closed if they are interrupted during hello.

Returns:

  • (Socket)

    The created socket.

Since:

  • 2.0.0

[ GitHub ]

  
# File 'lib/mongo/server/connection.rb', line 258

private def create_socket(context = nil)
  add_server_diagnostics do
    opts = ssl_options.merge(
      connection_address: address,
      connection_generation: generation,
      pipe: options[:pipe],
      connect_timeout: context&.remaining_timeout_sec,
      csot: !!context&.csot?
    )
    address.socket(socket_timeout, opts)
  end
end

#deliver(message, client, options = {}) (private)

Since:

  • 2.0.0

[ GitHub ]

  
# File 'lib/mongo/server/connection.rb', line 412

def deliver(message, client, options = {})
  handle_errors do
    super
  end
end

#disconnect!(options = nil) ⇒ true

Note:

Once a connection is disconnected, it should no longer be used. A new connection should be obtained from the connection pool which will either return a ready connection or create a new connection. If linting is enabled, reusing a disconnected connection will raise ::Mongo::Error::LintError. If linting is not enabled, a warning will be logged.

Note:

This method mutates the connection object by setting the socket to nil if the closing succeeded.

Disconnect the connection.

Parameters:

  • options (Hash) (defaults to: nil)

    a customizable set of options

Options Hash (options):

  • :reason (Symbol)

    The reason why the connection is being closed.

  • :interrupted (true | false)

    Whether or not the connection was interrupted.

Returns:

  • (true)

    If the disconnect succeeded.

Since:

  • 2.0.0

[ GitHub ]

  
# File 'lib/mongo/server/connection.rb', line 311

def disconnect!(options = nil)
  # NOTE: @closed may be true here but we also may have a socket.
  # Check the socket and not @closed flag.
  @auth_mechanism = nil
  @last_checkin = nil
  if socket
    begin
      socket.close
    rescue StandardError
      nil
    end
    @socket = nil
  end
  @closed = true
  interrupted! if options && options[:interrupted]

  # To satisfy CMAP spec tests, publish close events even if the
  # socket was never connected (and thus the ready event was never
  # published). But track whether we published close event and do not
  # publish it multiple times, unless the socket was reconnected -
  # in that case publish the close event once per socket close.
  unless @close_event_published
    reason = options && options[:reason]
    publish_cmap_event(
      Monitoring::Event::Cmap::ConnectionClosed.new(
        address,
        id,
        reason
      )
    )
    @close_event_published = true
  end

  true
end

#do_connectArray<Server::Description, String | Symbol> (private)

Separate method to permit easier mocking in the test suite.

Returns:

  • (Array<Server::Description, String | Symbol>)

    A server description instance from the hello response of the returned socket and the compressor to use.

Since:

  • 2.0.0

[ GitHub ]

  
# File 'lib/mongo/server/connection.rb', line 276

private def do_connect
  raise_if_closed!
  begin
    pending_connection = PendingConnection.new(
      socket, @server, monitoring, options.merge(id: id)
    )
    pending_connection.handshake_and_authenticate!
  rescue Exception
    socket&.close
    @socket = nil
    raise
  end

  [ pending_connection.description, pending_connection.compressor ]
end

#handle_errors (private)

Since:

  • 2.0.0

[ GitHub ]

  
# File 'lib/mongo/server/connection.rb', line 418

def handle_errors
  yield
rescue Error::SocketError => e
  @error = e
  @server.unknown!(
    generation: e.generation,
    # or description.service_id?
    service_id: e.service_id,
    stop_push_monitor: true
  )
  raise
rescue Error::SocketTimeoutError => e
  @error = e
  raise
end

#interrupted!

Mark the connection as interrupted.

Since:

  • 2.0.0

[ GitHub ]

  
# File 'lib/mongo/server/connection.rb', line 168

def interrupted!
  @interrupted = true
end

#pin(reason = :cursor)

Mark the connection as pinned for the given reason.

Parameters:

  • reason (Symbol) (defaults to: :cursor)

    The reason for pinning (:cursor or :transaction). Defaults to :cursor for backward compatibility.

Since:

  • 2.0.0

[ GitHub ]

  
# File 'lib/mongo/server/connection.rb', line 195

def pin(reason = :cursor)
  @pin_reasons << reason
end

#pingtrue, false

Deprecated.

No longer necessary with ::Mongo::Server Selection specification.

Note:

This uses a pre-serialized ping message for optimization.

Ping the connection to see if the server is responding to commands. This is non-blocking on the server side.

Examples:

Ping the connection.

connection.ping

Returns:

  • (true, false)

    If the server is accepting connections.

Since:

  • 2.1.0

[ GitHub ]

  
# File 'lib/mongo/server/connection.rb', line 360

def ping
  ensure_connected do |socket|
    reply = add_server_diagnostics do
      socket.write(PING_OP_MSG_BYTES)
      Protocol::Message.deserialize(socket, max_message_size)
    end
    reply.documents[0][Operation::Result::OK] == 1
  end
end

#raise_if_closed! (private)

Raises:

Since:

  • 2.0.0

[ GitHub ]

  
# File 'lib/mongo/server/connection.rb', line 434

def raise_if_closed!
  if error?
    raise Error::ConnectionPerished,
          "Connection #{generation}:#{id} for #{address.seed} is perished. Reconnecting closed or errored connections is no longer supported"
  end

  return unless closed?

  raise Error::ConnectionPerished,
        "Connection #{generation}:#{id} for #{address.seed} is closed. Reconnecting closed or errored connections is no longer supported"
end

#record_checkin!self

Record the last checkin time.

Examples:

Record the checkin time on this connection.

connection.record_checkin!

Since:

  • 2.5.0

[ GitHub ]

  
# File 'lib/mongo/server/connection.rb', line 389

def record_checkin!
  @last_checkin = Time.now
  self
end

#socket_timeoutFloat Also known as: #timeout

Get the timeout to execute an operation on a socket.

Returns:

  • (Float)

    The operation timeout in seconds.

Since:

  • 2.0.0

[ GitHub ]

  
# File 'lib/mongo/server/connection.rb', line 375

def socket_timeout
  @timeout ||= options[:socket_timeout]
end

#timeout

Alias for #socket_timeout.

[ GitHub ]

  
# File 'lib/mongo/server/connection.rb', line 379

alias timeout socket_timeout

#transportSymbol | nil

Get the transport type for this connection.

Returns:

  • (Symbol | nil)

    The transport type, :tcp or :unix, or nil if no socket.

Since:

  • 2.0.0

[ GitHub ]

  
# File 'lib/mongo/server/connection.rb', line 399

def transport
  return nil if @socket.nil?

  case @socket
  when Mongo::Socket::Unix
    :unix
  else
    :tcp
  end
end

#unpin(reason = :cursor)

Remove a pin from the connection for the given reason.

Parameters:

  • reason (Symbol) (defaults to: :cursor)

    The reason to unpin (:cursor or :transaction). Defaults to :cursor for backward compatibility.

Since:

  • 2.0.0

[ GitHub ]

  
# File 'lib/mongo/server/connection.rb', line 205

def unpin(reason = :cursor)
  @pin_reasons.delete(reason)
end

#unpin_all

Remove all pins from the connection.

Since:

  • 2.0.0

[ GitHub ]

  
# File 'lib/mongo/server/connection.rb', line 212

def unpin_all
  @pin_reasons.clear
end