2.2 KiB
tenant-cap
(no submodules)
Purpose
The tenant-cap module owns the per-tenant SSE connection counter the
engine consults during handshake. A tenant that has already reached
maxConnectionsPerTenant open connections receives 429 Too Many Requests with SSE_BUN.TENANT_CAP_EXCEEDED — the engine never opens
the long-lived stream, so the per-tenant ceiling is enforced exactly
at the handshake boundary and never as a mid-stream race.
Features
- O(1)
tryAcquire/releasekeyed byTenantId. count(tenantId)exposed so OTel gauges can sample without exposing the internal map.totalaggregate count for global capacity dashboards.- Tight error context:
tenantId,limit,currentattached to every thrownSseBunErrorso operators do not need to grep request logs. - Idempotent
release— releasing an unknown tenant does nothing.
Usage: Basic
import { createTenantConnectionCap } from "@suaveplan/api-sse-bun";
const cap = createTenantConnectionCap(1000);
cap.tryAcquire("acme" as never);
console.log(cap.count("acme" as never)); // 1
cap.release("acme" as never);
Usage: Advanced
import {
createTenantConnectionCap,
SSE_BUN_CODES,
SseBunError,
} from "@suaveplan/api-sse-bun";
const cap = createTenantConnectionCap(2);
const tenant = "acme" as never;
cap.tryAcquire(tenant);
cap.tryAcquire(tenant);
try {
cap.tryAcquire(tenant);
} catch (err) {
if (
err instanceof SseBunError &&
err.code === SSE_BUN_CODES.TENANT_CAP_EXCEEDED
) {
// return 429 ...
}
}
API Reference
interface TenantConnectionCap—tryAcquire(tenantId),release(tenantId),count(tenantId),total.function createTenantConnectionCap(max): TenantConnectionCap.
Implementation Notes
The cap uses a Map<TenantId, number> keyed by the branded tenant id;
the brand prevents an unsanitised header value from accidentally being
treated as a tenant key. release decrements when the count is > 1
and deletes the entry on the last release so the map's footprint
matches the live connection set. total is a running counter rather
than a derived sum so reading it from the OTel callback is O(1).