class Mongo::Server::Monitor::Connection

This class models the monitor connections and their behavior.

@since 2.0.0 @api private

Constants

ISMASTER

The command used for determining server status.

The case matters here for fail points.

@since 2.2.0

ISMASTER_BYTES

The raw bytes for the ismaster message.

@since 2.2.0

ISMASTER_MESSAGE

The constant for the ismaster command.

@since 2.2.0

ISMASTER_OP_MSG

The command used for determining server status formatted for an OP_MSG (server versions >= 3.6).

The case matters here for fail points.

@since 2.5.0

ISMASTER_OP_MSG_BYTES

The raw bytes for the ismaster OP_MSG message (server versions >= 3.6).

@since 2.5.0

ISMASTER_OP_MSG_MESSAGE

The constant for the ismaster command as an OP_MSG (server versions >= 3.6).

@since 2.5.0

Attributes

address[R]

@return [ Mongo::Address ] address The address to connect to.

options[R]

@return [ Hash ] options The passed in options.

server_connection_id[R]

Public Class Methods

new(address, options = {}) click to toggle source

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 nor handshakes); call connect! method on the connection object to create the network connection.

@note Monitoring connections do not authenticate.

@param [ Mongo::Address ] address The address the connection is for. @param [ Hash ] options The connection options.

@option options [ Mongo::Server::Monitor::AppMetadata ] :app_metadata

Metadata to use for handshake. If missing or nil, handshake will
not be performed. Although a Mongo::Server::AppMetadata instance
will also work, monitoring connections are meant to use
Mongo::Server::Monitor::AppMetadata instances in order to omit
performing SCRAM negotiation with the server, as monitoring
sockets do not authenticate.

@option options [ Array<String> ] :compressors A list of potential

compressors to use, in order of preference. The driver chooses the
first compressor that is also supported by the server. Currently the
driver only supports 'zlib'.

@option options [ Float ] :connect_timeout The timeout, in seconds,

to use for network operations. This timeout is used for all
socket operations rather than connect calls only, contrary to
what the name implies,

@since 2.0.0

# File lib/mongo/server/monitor/connection.rb, line 93
def initialize(address, options = {})
  @address = address
  @options = options.dup.freeze
  @app_metadata = options[:app_metadata]
  @socket = nil
  @pid = Process.pid
  @compressor = nil
end

Public Instance Methods

connect!() click to toggle source

Establishes a network connection to the target address.

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

@example Connect to the host.

connection.connect!

@note This method mutates the connection class by setting a socket if

one previously did not exist.

@return [ true ] If the connection succeeded.

@since 2.0.0

# File lib/mongo/server/monitor/connection.rb, line 189
def connect!
  if @socket
    raise ArgumentError, 'Monitoring connection already connected'
  end

  @socket = add_server_diagnostics do
    address.socket(socket_timeout, ssl_options.merge(
      connection_address: address, monitor: true))
  end
  true
end
disconnect!(options = nil) click to toggle source

Disconnect the connection.

@example Disconnect from the host.

connection.disconnect!

@note This method mutates the connection by setting the socket to nil

if the closing succeeded.

@note This method accepts an options argument for compatibility with

Server::Connections. However, all options are ignored.

@return [ true ] If the disconnect succeeded.

@since 2.0.0

# File lib/mongo/server/monitor/connection.rb, line 215
def disconnect!(options = nil)
  if socket
    socket.close rescue nil
    @socket = nil
  end
  true
end
dispatch(message) click to toggle source

Sends a message and returns the result.

@param [ Protocol::Message ] message The message to send.

@return [ Protocol::Message ] The result.

# File lib/mongo/server/monitor/connection.rb, line 128
def dispatch(message)
  dispatch_bytes(message.serialize.to_s)
end
dispatch_bytes(bytes, **opts) click to toggle source

Sends a preserialized message and returns the result.

@param [ String ] bytes The serialized message to send.

@option opts [ Numeric ] :read_socket_timeout The timeout to use for

each read operation.

@return [ Protocol::Message ] The result.

# File lib/mongo/server/monitor/connection.rb, line 140
def dispatch_bytes(bytes, **opts)
  write_bytes(bytes)
  read_response(
    socket_timeout: opts[:read_socket_timeout],
  )
end
handshake!() click to toggle source
# File lib/mongo/server/monitor/connection.rb, line 223
def handshake!
  payload = if @app_metadata
    @app_metadata.ismaster_bytes
  else
    log_warn("No app metadata provided for handshake with #{address}")
    ISMASTER_BYTES
  end
  message = dispatch_bytes(payload)
  reply = message.documents.first
  set_compressor!(reply)
  @server_connection_id = reply['connectionId']
  reply
rescue => exc
  msg = "Failed to handshake with #{address}"
  Utils.warn_bg_exception(msg, exc,
    logger: options[:logger],
    log_prefix: options[:log_prefix],
    bg_error_backtrace: options[:bg_error_backtrace],
  )
  raise
end
read_response(**opts) click to toggle source

@option opts [ Numeric ] :socket_timeout The timeout to use for

each read operation.
# File lib/mongo/server/monitor/connection.rb, line 161
def read_response(**opts)
  unless connected?
    raise ArgumentError, "Trying to read on an unconnected connection #{self}"
  end

  add_server_connection_id do
    add_server_diagnostics do
      Protocol::Message.deserialize(socket,
        Protocol::Message::MAX_MESSAGE_SIZE,
        nil,
        **opts)
    end
  end
end
socket_timeout() click to toggle source

Returns the monitoring socket timeout.

Note that monitoring connections use the connect timeout value as the socket timeout value. See the Server Discovery and Monitoring specification for details.

@return [ Float ] The socket timeout in seconds.

@since 2.4.3

# File lib/mongo/server/monitor/connection.rb, line 117
def socket_timeout
  options[:connect_timeout] || Server::CONNECT_TIMEOUT
end
write_bytes(bytes) click to toggle source
# File lib/mongo/server/monitor/connection.rb, line 147
def write_bytes(bytes)
  unless connected?
    raise ArgumentError, "Trying to dispatch on an unconnected connection #{self}"
  end

  add_server_connection_id do
    add_server_diagnostics do
      socket.write(bytes)
    end
  end
end

Private Instance Methods

add_server_connection_id() { || ... } click to toggle source
# File lib/mongo/server/monitor/connection.rb, line 247
def add_server_connection_id
  yield
rescue Mongo::Error => e
  if server_connection_id
    note = "sconn:#{server_connection_id}"
    e.add_note(note)
  end
  raise e
end