2.5 KiB
backpressure
(no submodules)
Purpose
Enforces the per-connection send-queue cap described in design §11.4. Each connection owns one BackpressureGuard instance; every outbound message increments the guard's depth, and the guard fires the eviction callback (and throws WS_BUN.BACKPRESSURE_EVICTED) the first time the depth exceeds maxQueuedMessages.
The guard reuses evaluateBackpressure from @suaveplan/api-ws so the eviction threshold stays identical across every engine that implements the contract — only the storage / wire layer differs.
Features
- Constant-time
enqueue()andrelease(n)operations. - Idempotent eviction — re-
enqueueafter eviction throws the sameWS_BUN.BACKPRESSURE_EVICTEDcode rather than firing the callback twice. - Exposes
queueddepth andisEvictedfor instruments and assertions.
Usage: Basic
import { BackpressureGuard } from "@suaveplan/api-ws-bun";
const guard = new BackpressureGuard("c1", 4, (id) => console.log(`evict ${id}`));
for (let i = 0; i < 4; i++) guard.enqueue();
console.log(guard.queued); // 4
guard.release(2);
console.log(guard.queued); // 2
Usage: Advanced
import { BackpressureGuard, WsBunError } from "@suaveplan/api-ws-bun";
const guard = new BackpressureGuard("c2", 2, () => undefined);
try {
for (let i = 0; i < 5; i++) guard.enqueue();
} catch (err) {
if (err instanceof WsBunError) {
// err.wsBunCode === "WS_BUN.BACKPRESSURE_EVICTED"
// The engine maps this onto a close frame with the same reason.
}
}
console.log(guard.isEvicted); // true
API Reference
new BackpressureGuard(connectionId, maxQueuedMessages, onEvict)— constructor.guard.enqueue(): "accept"— accounts for one outbound message; throws on overflow.guard.release(n?: number): void— frees upnslots after the socket flushed; defaults to1.guard.queued: number— current queue depth.guard.isEvicted: boolean— true once eviction has fired.
Implementation Notes
The guard intentionally throws inside enqueue() rather than returning "evict" to the caller. This lets the engine treat backpressure overflow as a thrown error that propagates through the OTel span automatically, keeping every overflow path symmetrical with the other WS_BUN.* codes.
release clamps the depth at zero so a buggy caller cannot make the guard "lend" capacity it never accounted for. The clamp is silent — overshoot is treated as ignorable bookkeeping noise.