Class: Pgbus::Web::HealthServer

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

Overview

Standalone HTTP health server for the supervisor process. When config.health_port is set, Supervisor#run starts one of these so a Kubernetes kubelet can probe the supervisor directly — the process that forks and watches workers — without the supervisor having to boot Rails, Puma, or the dashboard.

It is intentionally tiny: one accept-loop thread over a TCPServer that reads only the HTTP request line (GET /readyz HTTP/1.1), synthesizes a minimal Rack env, and hands it to Pgbus::Web::HealthApp#call. All routing and the OK/DEGRADED/STALLED → status mapping live in HealthApp, so the mounted-in- Rails path and this standalone path share exactly one implementation.

This is a health probe surface, not a general HTTP server: it speaks just enough HTTP/1.0 to answer a kubelet. It only parses the request line (method + path), ignores headers and body, and closes the connection after each response (no keep-alive).

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(port:, bind: "127.0.0.1", app: nil, logger: nil) ⇒ HealthServer

Returns a new instance of HealthServer.



39
40
41
42
43
44
45
46
47
# File 'lib/pgbus/web/health_server.rb', line 39

def initialize(port:, bind: "127.0.0.1", app: nil, logger: nil)
  @configured_port = port
  @bind = bind
  @app = app || HealthApp.new
  @logger = logger
  @server = nil
  @thread = nil
  @port = nil
end

Instance Attribute Details

#portInteger? (readonly)

Returns the bound port. Equals the configured port, or the OS-assigned port when the configured port was 0 (used in tests). nil before #start.

Returns:

  • (Integer, nil)

    the bound port. Equals the configured port, or the OS-assigned port when the configured port was 0 (used in tests). nil before #start.



37
38
39
# File 'lib/pgbus/web/health_server.rb', line 37

def port
  @port
end

Instance Method Details

#startObject

Bind the port and start the accept loop. Idempotent: a second call while running is a no-op (so a supervisor restart path can't double-bind).



51
52
53
54
55
56
57
58
# File 'lib/pgbus/web/health_server.rb', line 51

def start
  return if @server

  @server = TCPServer.new(@bind, @configured_port)
  @port = @server.addr[1]
  @thread = Thread.new { accept_loop }
  logger.info { "[Pgbus::Web::HealthServer] listening on #{@bind}:#{@port} (/livez, /readyz)" }
end

#stopObject

Close the listening socket (unblocking the accept loop, which then exits) and join the thread. Safe to call when never started or twice.



62
63
64
65
66
67
68
69
# File 'lib/pgbus/web/health_server.rb', line 62

def stop
  server = @server
  @server = nil
  close_socket(server)
  @thread&.join(2)
  @thread = nil
  @port = nil
end