Class: Mongo::Server::Monitor Private

Inherits:
Object
  • Object
show all
Extended by:
Forwardable
Includes:
BackgroundThread, 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 class is part of a private API. You should avoid using this class if possible, as it may be removed or be changed in the future.

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

Defined Under Namespace

Classes: AppMetadata, Connection

Constant Summary collapse

DEFAULT_HEARTBEAT_INTERVAL =

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

The default interval between server status refreshes is 10 seconds.

Since:

  • 2.0.0

10.freeze
MIN_SCAN_INTERVAL =

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

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

Since:

  • 2.0.0

0.5.freeze
RTT_WEIGHT_FACTOR =

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

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 BackgroundThread

#run!, #running?

Methods included from Loggable

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

Methods included from Event::Publisher

#publish

Constructor Details

#initialize(server, 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:

  • server (Server)

    The server to monitor.

  • event_listeners (Event::Listeners)

    The event listeners.

  • monitoring (Monitoring)

    The monitoring..

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

    The options.

Options Hash (options):

  • :connect_timeout (Float)

    The timeout, in seconds, to use when establishing the monitoring connection.

  • :heartbeat_interval (Float)

    The interval between regular server checks.

  • :logger (Logger)

    A custom logger to use.

  • :monitor_app_metadata (Mongo::Server::Monitor::AppMetadata)

    The metadata to use for regular monitoring connection.

  • :push_monitor_app_metadata (Mongo::Server::Monitor::AppMetadata)

    The metadata to use for push monitor’s connection.

  • :socket_timeout (Float)

    The timeout, in seconds, to execute operations on the monitoring connection.

Since:

  • 2.0.0



78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
# File 'lib/mongo/server/monitor.rb', line 78

def initialize(server, event_listeners, monitoring, options = {})
  unless monitoring.is_a?(Monitoring)
    raise ArgumentError, "Wrong monitoring type: #{monitoring.inspect}"
  end
  unless options[:app_metadata]
    raise ArgumentError, 'App metadata is required'
  end
  unless options[:push_monitor_app_metadata]
    raise ArgumentError, 'Push monitor app metadata is required'
  end
  @server = server
  @event_listeners = event_listeners
  @monitoring = monitoring
  @options = options.freeze
  @mutex = Mutex.new
  @sdam_mutex = Mutex.new
  @next_earliest_scan = @next_wanted_scan = Time.now
  @update_mutex = Mutex.new
end

Instance Attribute Details

#connectionMongo::Server::Monitor::Connection (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.

Returns connection The connection to use.

Returns:

Since:

  • 2.0.0



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

def connection
  @connection
end

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

Returns monitoring The monitoring.

Returns:

Since:

  • 2.0.0



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

def monitoring
  @monitoring
end

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

Returns options The server options.

Returns:

  • (Hash)

    options The server options.

Since:

  • 2.0.0



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

def options
  @options
end

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

Returns server The server that this monitor is monitoring.

Returns:

  • (Server)

    server The server that this monitor is monitoring.

Since:

  • 2.0.0



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

def server
  @server
end

Instance Method Details

#create_push_monitor!(topology_version) ⇒ Object

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



173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
# 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[:push_monitor_app_metadata],
        check_document: @connection.check_document
      )),
    )
  end
end

#do_workObject

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.

Perform a check of the server.

Since:

  • 2.0.0



138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
# 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

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.

The interval between regular server checks.

Returns:

  • (Float)

    The heartbeat interval, in seconds.

Since:

  • 2.0.0



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

def heartbeat_interval
  options[:heartbeat_interval] || DEFAULT_HEARTBEAT_INTERVAL
end

#push_monitorServer::PushMonitor | nil

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.

Returns The push monitor, if one is being used.

Returns:

Since:

  • 2.0.0



129
130
131
132
133
# File 'lib/mongo/server/monitor.rb', line 129

def push_monitor
  @update_mutex.synchronize do
    @push_monitor
  end
end

#restart!Thread

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.

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



270
271
272
273
274
275
276
# File 'lib/mongo/server/monitor.rb', line 270

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

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

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



236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
# 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_calculator.average_round_trip_time,
      minimum_round_trip_time: server.round_trip_time_calculator.minimum_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

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:

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



219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
# 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



162
163
164
165
166
167
168
169
170
171
# 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!Object

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



192
193
194
195
196
197
198
199
# 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

#to_sObject

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



278
279
280
# File 'lib/mongo/server/monitor.rb', line 278

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