Files
2026-05-27 23:29:53 +01:00

88 lines
3.3 KiB
Markdown

# `health` — broker health snapshot
<!-- begin:auto-docs -->
_(no submodules)_
<!-- end:auto-docs -->
## Purpose
This module is the pure, side-effect-free evaluator for the broker's health
status. It inspects the two underlying RESP clients (one publisher socket,
one subscriber socket) and folds their `isReady` flags plus the broker's
last observed error into a three-state status (`up`, `degraded`, `down`).
The host's readiness endpoint consumes this snapshot to decide whether to
report ready, partially ready, or unhealthy.
Keeping the evaluator pure means tests can probe every state combination
deterministically without a real Redis container — the broker's
integration test then pins that `up` is reached against a live container
and that the snapshot recovers after a forced socket close.
## Features
- Three-state status (`up`, `degraded`, `down`) with clear documented
semantics — degraded means in-flight publishes will queue per reconnect
strategy; down means new publishes will fail fast with `CONNECTION_LOST`.
- Pure function — no I/O, no global state, trivially testable.
- Optional `lastError` propagation so dashboards can show the most recent
underlying socket failure even after the broker has recovered.
## Usage: Basic
```ts
import { evaluateBrokerHealth } from "@suaveplan/api-ws-broker-redis/health";
const snap = evaluateBrokerHealth(publisher, subscriber, lastError);
if (snap.status === "down") {
return new Response("unavailable", { status: 503 });
}
```
## Usage: Advanced
```ts
import { evaluateBrokerHealth } from "@suaveplan/api-ws-broker-redis/health";
// Custom readiness probe that distinguishes degraded vs down.
function readiness(): { status: number; body: unknown } {
const snap = evaluateBrokerHealth(publisher, subscriber, lastError);
if (snap.status === "up") {
return { status: 200, body: { status: "ok" } };
}
if (snap.status === "degraded") {
return {
status: 200,
body: {
status: "degraded",
publisherReady: snap.publisherReady,
subscriberReady: snap.subscriberReady,
lastError: snap.lastError,
},
};
}
return { status: 503, body: { status: "down", lastError: snap.lastError } };
}
```
## API Reference
- `evaluateBrokerHealth(publisher, subscriber, lastError):
BrokerHealthSnapshot` — pure folder over the two clients.
- `BrokerHealthSnapshot { status, publisherReady, subscriberReady, lastError? }`.
- `BrokerHealthStatus = "up" | "degraded" | "down"`.
## Implementation Notes
The `lastError` field is set conditionally so the field is omitted from the
snapshot (rather than carrying `undefined`) when no error has ever been
observed. This matters for the JSON-serialised readiness response — a
dashboard parsing `lastError` should see "absent" vs "present" as a clean
boolean, not need to special-case `null` or `undefined`.
The publisher socket and subscriber socket are evaluated independently
because Redis's subscribe-mode connection is a separate TCP socket from the
reply-mode one; either can drop without the other. Operators see the actual
state of each socket via `publisherReady` / `subscriberReady` so they can
diagnose a partial outage (e.g. firewall dropping ESTABLISHED long-lived
subscribe sockets) directly from the readiness endpoint.