import { WS_CODES, WsError } from "../error-codes/error-codes.js"; /** * Policy describing how engines bound their per-connection outbound queue. * * `maxQueuedMessages` is the upper bound; once a connection has more * messages queued than this, the engine MUST close it with the * `BACKPRESSURE_EVICTED` reason and remove it from the registry. The * default of 256 matches design doc ยง11.4. */ export interface BackpressurePolicy { readonly maxQueuedMessages: number; } /** Default policy applied when no override is supplied. */ export const DEFAULT_BACKPRESSURE_POLICY: BackpressurePolicy = Object.freeze({ maxQueuedMessages: 256, }); /** * Reusable evaluator for engines. Given the current queue depth and a * policy, returns the action the engine MUST take. * * The contract package owns this helper so every concrete engine * (`api-ws-bun`, future browser shims) shares one definition of the * eviction trigger. */ export type BackpressureAction = "accept" | "evict"; export function evaluateBackpressure( queuedMessages: number, policy: BackpressurePolicy = DEFAULT_BACKPRESSURE_POLICY ): BackpressureAction { if (queuedMessages > policy.maxQueuedMessages) { return "evict"; } return "accept"; } /** * Helper that engines call when the policy has been violated. Throws a * `WsError` so the engine has one clean place to convert backpressure into * the documented close-frame reason. */ export function raiseBackpressureEvicted(connectionId: string): never { throw new WsError( WS_CODES.BACKPRESSURE_EVICTED, `connection ${connectionId} evicted: send queue overflow` ); }