Initial Commit
This commit is contained in:
62
packages/api-stack/api/api-sse-bun/src/limits/tenant-cap.ts
Normal file
62
packages/api-stack/api/api-sse-bun/src/limits/tenant-cap.ts
Normal file
@@ -0,0 +1,62 @@
|
||||
import type { TenantId } from "@suaveplan/api-types/tenant";
|
||||
import { SSE_BUN_CODES, SseBunError } from "../error-codes/error-codes.js";
|
||||
|
||||
/**
|
||||
* Per-tenant connection counter the engine consults on every handshake.
|
||||
*
|
||||
* Implementations expose `tryAcquire(tenantId)` (returns `true` and
|
||||
* increments on success, throws {@link SSE_BUN_CODES.TENANT_CAP_EXCEEDED}
|
||||
* on cap breach) plus `release(tenantId)` called on graceful close.
|
||||
*/
|
||||
export interface TenantConnectionCap {
|
||||
tryAcquire(tenantId: TenantId): true;
|
||||
release(tenantId: TenantId): void;
|
||||
count(tenantId: TenantId): number;
|
||||
readonly total: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a tenant cap with the given per-tenant ceiling.
|
||||
*/
|
||||
export function createTenantConnectionCap(
|
||||
maxConnectionsPerTenant: number
|
||||
): TenantConnectionCap {
|
||||
const counts = new Map<TenantId, number>();
|
||||
let total = 0;
|
||||
return {
|
||||
tryAcquire(tenantId): true {
|
||||
const current = counts.get(tenantId) ?? 0;
|
||||
if (current >= maxConnectionsPerTenant) {
|
||||
throw new SseBunError(
|
||||
SSE_BUN_CODES.TENANT_CAP_EXCEEDED,
|
||||
"error.sse_bun.tenant_cap_exceeded",
|
||||
{
|
||||
context: {
|
||||
tenantId,
|
||||
limit: maxConnectionsPerTenant,
|
||||
current,
|
||||
},
|
||||
}
|
||||
);
|
||||
}
|
||||
counts.set(tenantId, current + 1);
|
||||
total += 1;
|
||||
return true;
|
||||
},
|
||||
release(tenantId): void {
|
||||
const current = counts.get(tenantId) ?? 0;
|
||||
if (current <= 1) {
|
||||
counts.delete(tenantId);
|
||||
} else {
|
||||
counts.set(tenantId, current - 1);
|
||||
}
|
||||
total = Math.max(0, total - 1);
|
||||
},
|
||||
count(tenantId): number {
|
||||
return counts.get(tenantId) ?? 0;
|
||||
},
|
||||
get total() {
|
||||
return total;
|
||||
},
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user