Files
suaveplan/packages/api-stack/api/api-sse-bun/src/limits/tenant-cap.test.ts
2026-05-27 23:29:53 +01:00

51 lines
1.7 KiB
TypeScript

import type { TenantId } from "@suaveplan/api-types/tenant";
import { describe, expect, it } from "@suaveplan/testing/runner";
import { SSE_BUN_CODES, SseBunError } from "../error-codes/error-codes.js";
import { createTenantConnectionCap } from "./tenant-cap.js";
const T = (s: string): TenantId => s as TenantId;
describe("tenant-cap", () => {
it("acquires + releases up to the configured ceiling", () => {
const cap = createTenantConnectionCap(2);
cap.tryAcquire(T("acme"));
cap.tryAcquire(T("acme"));
expect(cap.count(T("acme"))).toBe(2);
expect(cap.total).toBe(2);
cap.release(T("acme"));
expect(cap.count(T("acme"))).toBe(1);
cap.release(T("acme"));
expect(cap.count(T("acme"))).toBe(0);
expect(cap.total).toBe(0);
}, 5000);
it("rejects the 1001st connection with TENANT_CAP_EXCEEDED", () => {
const cap = createTenantConnectionCap(2);
cap.tryAcquire(T("acme"));
cap.tryAcquire(T("acme"));
try {
cap.tryAcquire(T("acme"));
expect.fail("expected throw");
} catch (err) {
expect(err).toBeInstanceOf(SseBunError);
expect((err as SseBunError).code).toBe(
SSE_BUN_CODES.TENANT_CAP_EXCEEDED
);
}
}, 5000);
it("release on unknown tenant is a no-op", () => {
const cap = createTenantConnectionCap(1);
cap.release(T("never-acquired"));
expect(cap.total).toBe(0);
}, 5000);
it("tracks tenants independently", () => {
const cap = createTenantConnectionCap(1);
cap.tryAcquire(T("a"));
cap.tryAcquire(T("b"));
expect(cap.count(T("a"))).toBe(1);
expect(cap.count(T("b"))).toBe(1);
}, 5000);
});