Files
diegosouzapw--omniroute/tests/unit/lib/connection-cooldown-summary.test.ts
2026-07-13 13:39:12 +08:00

98 lines
3.5 KiB
TypeScript

/**
* TDD for F5.1 (Combo U1b Slice 2) — summarizeConnectionCooldown: aggregates the
* per-connection cooldown state (`rateLimitedUntil`) into a per-provider summary the
* cascade can badge, exposed by GET /api/monitoring/health as `connectionHealth`.
*
* Parsing of rateLimitedUntil is delegated to cooldownUntilMs (#3954) — it accepts
* ISO strings, Date objects, AND numeric epoch strings (the SQLite TEXT-affinity case).
*
* Run: node --import tsx/esm --test tests/unit/monitoring/connection-cooldown-summary.test.ts
*/
import { describe, it } from "node:test";
import assert from "node:assert/strict";
import { summarizeConnectionCooldown } from "../../../src/lib/monitoring/observability.ts";
const NOW = 1_000_000_000_000;
describe("summarizeConnectionCooldown", () => {
it("returns an empty map for no connections", () => {
assert.deepEqual(summarizeConnectionCooldown([], NOW), {});
});
it("omits providers whose connections are all available (no future rateLimitedUntil)", () => {
const out = summarizeConnectionCooldown(
[
{ provider: "openai", rateLimitedUntil: null },
{ provider: "openai", rateLimitedUntil: new Date(NOW - 5000).toISOString() }, // past → expired
],
NOW
);
assert.deepEqual(out, {});
});
it("reports coolingDown / total / soonestRetryAfterMs for a provider with cooling connections", () => {
const out = summarizeConnectionCooldown(
[
{ provider: "anthropic", rateLimitedUntil: new Date(NOW + 28_000).toISOString() },
{ provider: "anthropic", rateLimitedUntil: new Date(NOW + 60_000).toISOString() },
{ provider: "anthropic", rateLimitedUntil: null }, // available
],
NOW
);
assert.ok(out.anthropic);
assert.equal(out.anthropic.coolingDown, 2);
assert.equal(out.anthropic.total, 3);
assert.equal(
out.anthropic.soonestRetryAfterMs,
28_000,
"soonest = the connection that recovers first"
);
});
it("parses numeric-epoch-string rateLimitedUntil (SQLite TEXT-affinity, #3954)", () => {
const out = summarizeConnectionCooldown(
[{ provider: "glm", rateLimitedUntil: String(NOW + 15_000) }],
NOW
);
assert.ok(out.glm);
assert.equal(out.glm.coolingDown, 1);
assert.equal(out.glm.soonestRetryAfterMs, 15_000);
});
it("accepts a raw epoch number too", () => {
const out = summarizeConnectionCooldown(
[{ provider: "glm", rateLimitedUntil: NOW + 9000 }],
NOW
);
assert.equal(out.glm?.soonestRetryAfterMs, 9000);
});
it("groups connections per provider independently", () => {
const out = summarizeConnectionCooldown(
[
{ provider: "openai", rateLimitedUntil: new Date(NOW + 10_000).toISOString() },
{ provider: "anthropic", rateLimitedUntil: new Date(NOW + 40_000).toISOString() },
{ provider: "openai", rateLimitedUntil: null },
],
NOW
);
assert.equal(out.openai.coolingDown, 1);
assert.equal(out.openai.total, 2);
assert.equal(out.anthropic.coolingDown, 1);
assert.equal(out.anthropic.total, 1);
});
it("ignores connections without a provider and never returns negative retry", () => {
const out = summarizeConnectionCooldown(
[
{ rateLimitedUntil: new Date(NOW + 5000).toISOString() }, // no provider
{ provider: "x", rateLimitedUntil: new Date(NOW + 1).toISOString() },
],
NOW
);
assert.equal(Object.keys(out).length, 1);
assert.ok(out.x.soonestRetryAfterMs >= 0);
});
});