Class: Mongo::Server::Monitor

Inherits:
Object
  • Object
show all
Extended by:
Forwardable
Includes:
Event::Publisher, Loggable
Defined in:
lib/mongo/server/monitor.rb,
lib/mongo/server/monitor/connection.rb,
lib/mongo/server/monitor/app_metadata.rb

Overview

This object is responsible for keeping server status up to date, running in a separate thread as to not disrupt other operations.

Since:

  • 2.0.0

Defined Under Namespace

Classes: AppMetadata, Connection

Constant Summary collapse

HEARTBEAT_FREQUENCY =

The default time for a server to refresh its status is 10 seconds.

Since:

  • 2.0.0

10.freeze
MIN_SCAN_FREQUENCY =

The minimum time between forced server scans. Is minHeartbeatFrequencyMS in the SDAM spec.

Since:

  • 2.0.0

0.5.freeze
RTT_WEIGHT_FACTOR =
Deprecated.

Will be removed in version 3.0.

The weighting factor (alpha) for calculating the average moving round trip time.

Since:

  • 2.0.0

0.2.freeze

Constants included from Loggable

Loggable::PREFIX

Instance Attribute Summary collapse

Attributes included from Event::Publisher

#event_listeners

Instance Method Summary collapse

Methods included from Event::Publisher

#publish

Methods included from Loggable

#log_debug, #log_error, #log_fatal, #log_info, #log_warn, #logger

Constructor Details

#initialize(address, event_listeners, monitoring, options = {}) ⇒ Monitor

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Note:

Monitor must never be directly instantiated outside of a Server.

Create the new server monitor.

Examples:

Create the server monitor.

Mongo::Server::Monitor.new(address, listeners, monitoring)

Parameters:

  • address (Address)

    The address to monitor.

  • event_listeners (Event::Listeners)

    The event listeners.

  • monitoring (Monitoring)

    The monitoring..

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

    The options.

Options Hash (options):

  • :heartbeat_frequency (Float)

    The interval, in seconds, between server description refreshes via ismaster.

Since:

  • 2.0.0



60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
# File 'lib/mongo/server/monitor.rb', line 60

def initialize(address, event_listeners, monitoring, options = {})
  unless monitoring.is_a?(Monitoring)
    raise ArgumentError, "Wrong monitoring type: #{monitoring.inspect}"
  end
  @description = Description.new(address, {})
  @event_listeners = event_listeners
  @monitoring = monitoring
  @options = options.freeze
  @round_trip_time_averager = RoundTripTimeAverager.new
  @scan_semaphore = Semaphore.new
  # This is a Mongo::Server::Monitor::Connection
  @connection = Connection.new(address, options)
  @last_scan = nil
  @mutex = Mutex.new
end

Instance Attribute Details

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

Returns connection The connection to use.

Returns:

Since:

  • 2.0.0



77
78
79
# File 'lib/mongo/server/monitor.rb', line 77

def connection
  @connection
end

#descriptionServer::Description (readonly)

Returns description The server description the monitor refreshes.

Returns:

Since:

  • 2.0.0



81
82
83
# File 'lib/mongo/server/monitor.rb', line 81

def description
  @description
end

#last_scanTime (readonly)

Returns last_scan The time when the last server scan started.

Returns:

  • (Time)

    last_scan The time when the last server scan started.

Since:

  • 2.4.0



89
90
91
# File 'lib/mongo/server/monitor.rb', line 89

def last_scan
  @last_scan
end

#monitoringMonitoring (readonly)

Returns monitoring The monitoring.

Returns:

Since:

  • 2.0.0



96
97
98
# File 'lib/mongo/server/monitor.rb', line 96

def monitoring
  @monitoring
end

#optionsHash (readonly)

Returns options The server options.

Returns:

  • (Hash)

    options The server options.

Since:

  • 2.0.0



84
85
86
# File 'lib/mongo/server/monitor.rb', line 84

def options
  @options
end

#round_trip_time_averagerObject (readonly)

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Since:

  • 2.0.0



221
222
223
# File 'lib/mongo/server/monitor.rb', line 221

def round_trip_time_averager
  @round_trip_time_averager
end

#scan_semaphoreObject (readonly)

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Since:

  • 2.0.0



112
113
114
# File 'lib/mongo/server/monitor.rb', line 112

def scan_semaphore
  @scan_semaphore
end

Instance Method Details

#heartbeat_frequencyInteger

Get the refresh interval for the server. This will be defined via an option or will default to 10.

Examples:

Get the refresh interval.

server.heartbeat_frequency

Returns:

  • (Integer)

    The heartbeat frequency, in seconds.

Since:

  • 2.0.0



107
108
109
# File 'lib/mongo/server/monitor.rb', line 107

def heartbeat_frequency
  @heartbeat_frequency ||= options[:heartbeat_frequency] || HEARTBEAT_FREQUENCY
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



212
213
214
215
216
217
218
# File 'lib/mongo/server/monitor.rb', line 212

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

#run!Thread

Runs the server monitor. Refreshing happens on a separate thread per server.

Examples:

Run the monitor.

monitor.run

Returns:

  • (Thread)

    The thread the monitor runs on.

Since:

  • 2.0.0



123
124
125
126
127
128
129
130
# File 'lib/mongo/server/monitor.rb', line 123

def run!
  @thread = Thread.new(heartbeat_frequency) do |i|
    loop do
      scan!
      @scan_semaphore.wait(i)
    end
  end
end

#scan!Description

Note:

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

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_FREQUENCY seconds ago, sleep until MIN_SCAN_FREQUENCY seconds have passed since the last check. Then perform the check which involves running isMaster on the server being monitored and updating the server description as a result.

Examples:

Run a scan.

monitor.scan!

Returns:

Since:

  • 2.0.0



150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
# File 'lib/mongo/server/monitor.rb', line 150

def scan!
  throttle_scan_frequency!
  result = ismaster
  new_description = Description.new(description.address, result,
    @round_trip_time_averager.average_round_trip_time)
  publish(Event::DESCRIPTION_CHANGED, description, new_description)
  # If this server's response has a mismatched me, or for other reasons,
  # this server may be removed from topology. When this happens the
  # monitor thread gets killed. As a result, any code after the publish
  # call may not run in a particular monitor instance, hence there
  # shouldn't be any code here.
  @description = new_description
  # This call can be after the publish event because if the
  # monitoring thread gets killed the server is closed and no client
  # should be waiting for it
  if options[:server_selection_semaphore]
    options[:server_selection_semaphore].broadcast
  end
  @description
end

#stop!(wait = false) ⇒ Boolean

Stops the server monitor. Kills the thread so it doesn't continue taking memory and sending commands to the connection.

Examples:

Stop the monitor.

monitor.stop!

Parameters:

  • wait (Boolean) (defaults to: false)

    Whether to wait for background threads to finish running.

Returns:

  • (Boolean)

    Is the thread stopped?

Since:

  • 2.0.0



183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
# File 'lib/mongo/server/monitor.rb', line 183

def stop!(wait=false)
  # Although disconnect! documentation implies a possibility of
  # failure, all of our disconnects always return true
  if connection.disconnect!
    if @thread
      @thread.kill
      if wait
        @thread.join
        @thread = nil
        true
      else
        !@thread.alive?
      end
    else
      true
    end
  else
    false
  end
end