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

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.

Raises:

  • (ArgumentError)

Since:

  • 2.0.0



76
77
78
79
80
81
82
83
84
85
86
87
88
89
# File 'lib/mongo/server/monitor.rb', line 76

def initialize(server, event_listeners, monitoring, options = {})
  raise ArgumentError, "Wrong monitoring type: #{monitoring.inspect}" unless monitoring.is_a?(Monitoring)
  raise ArgumentError, 'App metadata is required' unless options[:app_metadata]
  raise ArgumentError, 'Push monitor app metadata is required' unless options[:push_monitor_app_metadata]

  @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



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

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



118
119
120
# File 'lib/mongo/server/monitor.rb', line 118

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



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

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



93
94
95
# File 'lib/mongo/server/monitor.rb', line 93

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



162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
# File 'lib/mongo/server/monitor.rb', line 162

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

    @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



131
132
133
134
135
136
137
138
139
140
141
142
143
# File 'lib/mongo/server/monitor.rb', line 131

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
    break unless delta > 0

    signaled = server.scan_semaphore.wait(delta)
    break if signaled || @stop_requested
  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



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

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



122
123
124
125
126
# File 'lib/mongo/server/monitor.rb', line 122

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



257
258
259
260
261
262
263
# File 'lib/mongo/server/monitor.rb', line 257

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



223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
# File 'lib/mongo/server/monitor.rb', line 223

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



206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
# File 'lib/mongo/server/monitor.rb', line 206

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 StandardError => 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



151
152
153
154
155
156
157
158
159
160
# File 'lib/mongo/server/monitor.rb', line 151

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



179
180
181
182
183
184
185
186
# File 'lib/mongo/server/monitor.rb', line 179

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



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

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