Class: Pgbus::Web::HealthApp

Inherits:
Object
  • Object
show all
Defined in:
lib/pgbus/web/health_app.rb

Overview

Plain Rack app exposing HTTP liveness and readiness probes for orchestrators (Kubernetes kubelet, load balancers). Mount it in the host Rails app — no auth, no DB access on the liveness path:

# config/routes.rb
mount Pgbus::Web::HealthApp.new => "/pgbus/health"

# kubelet
livenessProbe:  { httpGet: { path: /pgbus/health/livez, port: 3000 } }
readinessProbe: { httpGet: { path: /pgbus/health/readyz, port: 3000 } }

The supervisor process can also serve these two paths standalone via HealthServer when config.health_port is set — that path synthesizes a minimal Rack env and calls this same #call, so the routing and verdict logic live in exactly one place.

Routing (env-only, no Rack::Request so it works under the bare-socket HealthServer too):

GET  /livez  → 200 text/plain "ok", unconditionally, NO database access
             (the serving process is up — that is all liveness means).
GET  /readyz → build a DataSource, run MCP::HealthAnalyzer#verdict:
               OK / DEGRADED → 200, STALLED → 503, body = verdict JSON.
             Any StandardError (DB unreachable) → 503 {"status":"ERROR"},
             logged via Pgbus.logger (never swallowed).
unknown path → 404; non-GET on a known path → 405.

Constant Summary collapse

LIVEZ =
"/livez"
READYZ =
"/readyz"

Instance Method Summary collapse

Constructor Details

#initialize(data_source: nil) ⇒ HealthApp

Returns a new instance of HealthApp.

Parameters:

  • data_source (Pgbus::Web::DataSource, nil) (defaults to: nil)

    read layer for /readyz. nil (the default) builds a fresh DataSource per readiness check, which avoids serving stale metrics from a long-lived app's memoized instance.



52
53
54
# File 'lib/pgbus/web/health_app.rb', line 52

def initialize(data_source: nil)
  @data_source = data_source
end

Instance Method Details

#call(env) ⇒ Object



56
57
58
59
60
61
62
# File 'lib/pgbus/web/health_app.rb', line 56

def call(env)
  path = env["PATH_INFO"].to_s
  return not_found unless KNOWN_PATHS.include?(path)
  return method_not_allowed unless env["REQUEST_METHOD"] == "GET"

  path == LIVEZ ? livez : readyz
end