Files
skills/docs/api-stack/api/api-ws-bun/src/backpressure/backpressure.md
2026-05-29 08:20:56 +01:00

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() and release(n) operations.
  • Idempotent eviction — re-enqueue after eviction throws the same WS_BUN.BACKPRESSURE_EVICTED code rather than firing the callback twice.
  • Exposes queued depth and isEvicted for 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 up n slots after the socket flushed; defaults to 1.
  • 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.