Class: Usps::Support::HealthMonitor
- Inherits:
-
Object
- Object
- Usps::Support::HealthMonitor
- Defined in:
- lib/usps/support/health_monitor.rb
Overview
Keeps a process-local snapshot of the latest health-check results so /health can answer from memory instead of running the checks on the request thread. See doc/health_check_refresh_design.md for the rationale.
runner is a callable that runs one full round of checks and returns whatever the caller needs to render (HealthController returns { app:, results:, measurements: }). It is expected to bound its own checks; the monitor adds no timeout of its own.
One monitor exists per concrete HealthController subclass, per process. It is created lazily on the first request, so the background thread starts after Passenger forks its workers (threads do not survive fork).
Defined Under Namespace
Classes: Snapshot
Instance Method Summary collapse
-
#current ⇒ Object
The latest results.
- #fresh?(snapshot) ⇒ Boolean
-
#initialize(interval:, max_age:, runner:, background: true, clock: nil) ⇒ HealthMonitor
constructor
interval: seconds between background refreshes max_age: a snapshot older than this is refreshed inline before use, so a wedged or never-started background thread can't serve dangerously old data runner: callable that runs one round of checks and returns the render data background: start the background refresher (false in tests, so refreshes are synchronous) clock: monotonic clock (seconds) to read; injectable for deterministic staleness tests.
-
#refresh ⇒ Object
Runs one round of checks and stores the snapshot; returns the fresh data.
-
#stop ⇒ Object
Stops the background refresher.
Constructor Details
#initialize(interval:, max_age:, runner:, background: true, clock: nil) ⇒ HealthMonitor
interval: seconds between background refreshes max_age: a snapshot older than this is refreshed inline before use, so a wedged or never-started background thread can't serve dangerously old data runner: callable that runs one round of checks and returns the render data background: start the background refresher (false in tests, so refreshes are synchronous) clock: monotonic clock (seconds) to read; injectable for deterministic staleness tests
25 26 27 28 29 30 31 32 |
# File 'lib/usps/support/health_monitor.rb', line 25 def initialize(interval:, max_age:, runner:, background: true, clock: nil) @interval = interval @max_age = max_age @runner = runner @background = background @clock = clock || -> { Process.clock_gettime(Process::CLOCK_MONOTONIC) } @mutex = Mutex.new end |
Instance Method Details
#current ⇒ Object
The latest results. Serves a fresh cached snapshot without touching any dependency; on a cold (first call) or stale snapshot, refreshes inline so the answer is never dangerously old. Also starts the background refresher on first use. Returns the runner's data, or nil only if the very first refresh failed and there is no prior snapshot to fall back on.
38 39 40 41 42 43 44 45 |
# File 'lib/usps/support/health_monitor.rb', line 38 def current ensure_running if @background snapshot = @snapshot return snapshot.data if snapshot && fresh?(snapshot) refresh end |
#fresh?(snapshot) ⇒ Boolean
60 |
# File 'lib/usps/support/health_monitor.rb', line 60 def fresh?(snapshot) = (@clock.call - snapshot.at) <= @max_age |
#refresh ⇒ Object
Runs one round of checks and stores the snapshot; returns the fresh data. On a runner error, keeps the last good snapshot and returns its data (nil if there was none), so a transient failure to run the checks never blanks out /health.
50 51 52 53 54 55 56 57 58 |
# File 'lib/usps/support/health_monitor.rb', line 50 def refresh @mutex.synchronize do data = @runner.call @snapshot = Snapshot.new(data:, at: @clock.call) data end rescue StandardError @snapshot&.data end |
#stop ⇒ Object
Stops the background refresher. Used by tests; also safe to call on shutdown.
63 64 65 66 67 68 |
# File 'lib/usps/support/health_monitor.rb', line 63 def stop @mutex.synchronize do @thread&.kill @thread = nil end end |