Initial Commit
This commit is contained in:
53
packages/api-stack/api/api-ws/src/heartbeat/heartbeat.ts
Normal file
53
packages/api-stack/api/api-ws/src/heartbeat/heartbeat.ts
Normal file
@@ -0,0 +1,53 @@
|
||||
import { WS_CODES, WsError } from "../error-codes/error-codes.js";
|
||||
|
||||
/**
|
||||
* Policy describing the engine's ping/pong cadence and failure threshold.
|
||||
*
|
||||
* Defaults match design doc §11.4: ping every 30000ms, declare the
|
||||
* connection dead after two consecutive missed pongs.
|
||||
*/
|
||||
export interface HeartbeatPolicy {
|
||||
readonly heartbeatMs: number;
|
||||
readonly maxMissedPongs: number;
|
||||
}
|
||||
|
||||
/** Default policy applied when no override is supplied. */
|
||||
export const DEFAULT_HEARTBEAT_POLICY: HeartbeatPolicy = Object.freeze({
|
||||
heartbeatMs: 30000,
|
||||
maxMissedPongs: 2,
|
||||
});
|
||||
|
||||
/** Action returned by {@link evaluateHeartbeat}. */
|
||||
export type HeartbeatAction = "ok" | "ping" | "abort";
|
||||
|
||||
/**
|
||||
* Stateless evaluator: given the engine's current view of "ms since last
|
||||
* pong" + "consecutive missed pongs", returns the action the engine must
|
||||
* take next.
|
||||
*
|
||||
* - `ok` — within tolerance, nothing to do.
|
||||
* - `ping` — heartbeat interval elapsed; engine should send a ping.
|
||||
* - `abort` — `maxMissedPongs` reached; engine MUST close the connection
|
||||
* with `ABNORMAL` and emit `WS.HEARTBEAT_FAILED`.
|
||||
*/
|
||||
export function evaluateHeartbeat(
|
||||
msSinceLastPong: number,
|
||||
consecutiveMissedPongs: number,
|
||||
policy: HeartbeatPolicy = DEFAULT_HEARTBEAT_POLICY
|
||||
): HeartbeatAction {
|
||||
if (consecutiveMissedPongs >= policy.maxMissedPongs) {
|
||||
return "abort";
|
||||
}
|
||||
if (msSinceLastPong >= policy.heartbeatMs) {
|
||||
return "ping";
|
||||
}
|
||||
return "ok";
|
||||
}
|
||||
|
||||
/** Helper that throws the canonical `WsError`. */
|
||||
export function raiseHeartbeatFailed(connectionId: string): never {
|
||||
throw new WsError(
|
||||
WS_CODES.HEARTBEAT_FAILED,
|
||||
`connection ${connectionId} failed heartbeat: two missed pongs`
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user