123456789_123456789_123456789_123456789_123456789_

Class: Mongo::Server::Monitor Private

Do not use. This class is for internal use only.
Relationships & Source Files
Namespace Children
Classes:
Super Chains via Extension / Inclusion / Inheritance
Class Chain:
self, Forwardable
Instance Chain:
Inherits: Object
Defined in: lib/mongo/server/monitor.rb,
lib/mongo/server/monitor/app_metadata.rb,
lib/mongo/server/monitor/connection.rb

Overview

Responsible for periodically polling a server via hello commands to keep the server’s status up to date.

Does all work in a background thread so as to not interfere with other operations performed by the driver.

Since:

  • 2.0.0

Constant Summary

::Mongo::Loggable - Included

PREFIX

Class Method Summary

Instance Attribute Summary

::Mongo::BackgroundThread - Included

::Mongo::Event::Publisher - Included

Instance Method Summary

::Mongo::BackgroundThread - Included

#run!

Start the background thread.

#stop!

Stop the background thread and wait for to terminate for a reasonable amount of time.

#do_work

Override this method to do the work in the background thread.

#pre_stop

Override this method to perform additional signaling for the background thread to stop.

#start!,
#wait_for_stop

Waits for the thread to die, with a timeout.

::Mongo::Event::Publisher - Included

#publish

Publish the provided event.

::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

Instance Attribute Details

#connectionMongo::Server::Monitor::Connection (readonly)

Returns:

Since:

  • 2.0.0

[ GitHub ]

  
# File 'lib/mongo/server/monitor.rb', line 103

attr_reader :connection

#monitoringMonitoring (readonly)

Returns:

Since:

  • 2.0.0

[ GitHub ]

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

attr_reader :monitoring

#optionsHash (readonly)

Returns:

  • (Hash)

    options The server options.

Since:

  • 2.0.0

[ GitHub ]

  
# File 'lib/mongo/server/monitor.rb', line 106

attr_reader :options

#serverServer (readonly)

Returns:

  • (Server)

    server The server that this monitor is monitoring.

Since:

  • 2.0.0

[ GitHub ]

  
# File 'lib/mongo/server/monitor.rb', line 100

attr_reader :server

Instance Method Details

#check (private)

Since:

  • 2.0.0

[ GitHub ]

  
# File 'lib/mongo/server/monitor.rb', line 301

def check
  if @connection && @connection.pid != Process.pid
    log_warn("Detected PID change - Mongo client should have been reconnected (old pid #{@connection.pid}, new pid #{Process.pid}")
    @connection.disconnect!
    @connection = nil
  end

  if @connection
    result = server.round_trip_time_averager.measure do
      begin
        doc = @connection.check_document
        cmd = Protocol::Query.new(
          Database::ADMIN, Database::COMMAND, doc, :limit => -1
        )
        message = @connection.dispatch_bytes(cmd.serialize.to_s)
        message.documents.first
      rescue Mongo::Error
        @connection.disconnect!
        @connection = nil
        raise
      end
    end
  else
    connection = Connection.new(server.address, options)
    connection.connect!
    result = server.round_trip_time_averager.measure do
      connection.handshake!
    end
    @connection = connection
    if tv_doc = result['topologyVersion']
      # Successful response, server 4.4+
      create_push_monitor!(TopologyVersion.new(tv_doc))
      push_monitor.run!
    else
      # Failed response or pre-4.4 server
      stop_push_monitor!
    end
    result
  end
  result
end

#create_push_monitor!(topology_version)

Since:

  • 2.0.0

[ GitHub ]

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

def create_push_monitor!(topology_version)
  @update_mutex.synchronize do
    if @push_monitor && !@push_monitor.running?
      @push_monitor = nil
    end

    @push_monitor ||= PushMonitor.new(
      self,
      topology_version,
      monitoring,
      **Utils.shallow_symbolize_keys(options.merge(
        socket_timeout: heartbeat_interval + connection.socket_timeout,
        app_metadata: options[:],
        check_document: @connection.check_document
      )),
    )
  end
end

#do_scan (private)

Since:

  • 2.0.0

[ GitHub ]

  
# File 'lib/mongo/server/monitor.rb', line 285

def do_scan
  begin
    monitoring.publish_heartbeat(server) do
      check
    end
  rescue => exc
    msg = "Error checking #{server.address}"
    Utils.warn_bg_exception(msg, exc,
      logger: options[:logger],
      log_prefix: options[:log_prefix],
      bg_error_backtrace: options[:bg_error_backtrace],
    )
    raise exc
  end
end

#do_work

Perform a check of the server.

Since:

  • 2.0.0

[ GitHub ]

  
# File 'lib/mongo/server/monitor.rb', line 138

def do_work
  scan!
  # @next_wanted_scan may be updated by the push monitor.
  # However we need to check for termination flag so that the monitor
  # thread exits when requested.
  loop do
    delta = @next_wanted_scan - Time.now
    if delta > 0
      signaled = server.scan_semaphore.wait(delta)
      if signaled || @stop_requested
        break
      end
    else
      break
    end
  end
end

#heartbeat_intervalFloat

The interval between regular server checks.

Returns:

  • (Float)

    The heartbeat interval, in seconds.

Since:

  • 2.0.0

[ GitHub ]

  
# File 'lib/mongo/server/monitor.rb', line 111

def heartbeat_interval
  options[:heartbeat_interval] || DEFAULT_HEARTBEAT_INTERVAL
end

#pre_stop (private)

Since:

  • 2.0.0

[ GitHub ]

  
# File 'lib/mongo/server/monitor.rb', line 281

def pre_stop
  server.scan_semaphore.signal
end

#push_monitorServer::PushMonitor | nil

Returns:

Since:

  • 2.0.0

[ GitHub ]

  
# File 'lib/mongo/server/monitor.rb', line 129

def push_monitor
  @update_mutex.synchronize do
    @push_monitor
  end
end

#restart!Thread

Restarts the server monitor unless the current thread is alive.

Examples:

Restart the monitor.

monitor.restart!

Returns:

  • (Thread)

    The thread the monitor runs on.

Since:

  • 2.1.0

[ GitHub ]

  
# File 'lib/mongo/server/monitor.rb', line 267

def restart!
  if @thread && @thread.alive?
    @thread
  else
    run!
  end
end

#run_sdam_flow(result, awaited: false, scan_error: nil)

Since:

  • 2.0.0

[ GitHub ]

  
# File 'lib/mongo/server/monitor.rb', line 236

def run_sdam_flow(result, awaited: false, scan_error: nil)
  @sdam_mutex.synchronize do
    old_description = server.description

    new_description = Description.new(server.address, result,
      average_round_trip_time: server.round_trip_time_averager.average_round_trip_time
    )

    server.cluster.run_sdam_flow(server.description, new_description, awaited: awaited, scan_error: scan_error)

    server.description.tap do |new_description|
      unless awaited
        if new_description.unknown? && !old_description.unknown?
          @next_earliest_scan = @next_wanted_scan = Time.now
        else
          @next_earliest_scan = Time.now + MIN_SCAN_INTERVAL
          @next_wanted_scan = Time.now + heartbeat_interval
        end
      end
    end
  end
end

#scan!Description

Note:

If the system clock moves backwards, this method can sleep for a very long time.

Note:

The return value of this method is deprecated. In version 3.0.0 this method will not have a return value.

Perform a check of the server with throttling, and update the server’s description and average round trip time.

If the server was checked less than MIN_SCAN_INTERVAL seconds ago, sleep until MIN_SCAN_INTERVAL seconds have passed since the last check. Then perform the check which involves running hello on the server being monitored and updating the server description as a result.

Returns:

Since:

  • 2.0.0

[ GitHub ]

  
# File 'lib/mongo/server/monitor.rb', line 219

def scan!
  # Ordinarily the background thread would invoke this method.
  # But it is also possible to invoke scan! directly on a monitor.
  # Allow only one scan to be performed at a time.
  @mutex.synchronize do
    throttle_scan_frequency!

    begin
      result = do_scan
    rescue => e
      run_sdam_flow({}, scan_error: e)
    else
      run_sdam_flow(result)
    end
  end
end

#stop!true | false

Stop the background thread and wait for it to terminate for a reasonable amount of time.

Returns:

  • (true | false)

    Whether the thread was terminated.

Since:

  • 2.0.0

[ GitHub ]

  
# File 'lib/mongo/server/monitor.rb', line 162

def stop!
  stop_push_monitor!

  # Forward super's return value
  super.tap do
    # Important: disconnect should happen after the background thread
    # terminates.
    connection&.disconnect!
  end
end

#stop_push_monitor!

Since:

  • 2.0.0

[ GitHub ]

  
# File 'lib/mongo/server/monitor.rb', line 192

def stop_push_monitor!
  @update_mutex.synchronize do
    if @push_monitor
      @push_monitor.stop!
      @push_monitor = nil
    end
  end
end

#throttle_scan_frequency! (private)

Note:

If the system clock is set to a time in the past, this method can sleep for a very long time.

Since:

  • 2.0.0

[ GitHub ]

  
# File 'lib/mongo/server/monitor.rb', line 345

def throttle_scan_frequency!
  delta = @next_earliest_scan - Time.now
  if delta > 0
    sleep(delta)
  end
end

#to_s

Since:

  • 2.0.0

[ GitHub ]

  
# File 'lib/mongo/server/monitor.rb', line 275

def to_s
  "#<#{self.class.name}:#{object_id} #{server.address}>"
end