refactor(usage): extract pure quota-normalize helpers from providerLimits.ts (#5730)

providerLimits.ts (954 lines, frozen-baselined) is the heavily DB/network-coupled
provider quota sync module. Extract a small, fully SELF-CONTAINED leaf of pure
quota-key/quota-value normalization helpers (+ the isRecord type guard they
share), leaving all sync/DB/network code in the host:

  - providerLimits/quotaNormalize.ts (72)  isRecord, isUsageQuotaKeyAllowed,
    normalizeUsageQuotaKey, normalizeUsageQuotasForProvider,
    sanitizeUsageQuotasForProvider

Host providerLimits.ts: 954 -> 890. The leaf imports only the external
antigravity/agy model-alias helpers the moved bodies reference (moved from the
host's import block) — it does NOT import the host, so check:cycles stays clean
(no cycle). isRecord (used ~9x in the host) is co-extracted and imported back.
These five were all module-internal, so the public API is unchanged (13
exported functions). Bodies moved byte-identical.

Behavior-preserving: 18 existing provider-limits consumer tests stay green
(sanitize-scope 3, db-provider-limits 3, proxy-fail-closed 3,
rotating-expired-guard 7, codex-quota-sync 2); new
tests/unit/providerlimits-quotanormalize-split.test.ts (19 assertions) pins
isRecord + isUsageQuotaKeyAllowed + guards the 13-function public API.

Refs #3501.
This commit is contained in:
Diego Rodrigues de Sa e Souza
2026-06-30 20:33:35 -03:00
committed by GitHub
parent 04d22a784d
commit ba7f2145d0
3 changed files with 182 additions and 70 deletions

View File

@@ -27,12 +27,13 @@ import {
extractCodeAssistSubscriptionTier,
} from "@omniroute/open-sse/services/codeAssistSubscription.ts";
import { runWithProxyContext } from "@omniroute/open-sse/utils/proxyFetch.ts";
import {
isUserCallableAntigravityModelId,
toClientAntigravityModelId,
} from "@omniroute/open-sse/config/antigravityModelAliases.ts";
import { isUserCallableAgyModelId } from "@omniroute/open-sse/config/agyModels.ts";
import { onUsageRecorded } from "./usageEvents";
import {
isRecord,
isUsageQuotaKeyAllowed,
normalizeUsageQuotasForProvider,
sanitizeUsageQuotasForProvider,
} from "./providerLimits/quotaNormalize";
type JsonRecord = Record<string, unknown>;
type SyncSource = "manual" | "scheduled";
@@ -79,10 +80,6 @@ const PROVIDER_LIMITS_AUTO_SYNC_SETTING_KEY = "provider_limits_auto_sync_last_ru
const DEFAULT_PROVIDER_LIMITS_POST_USAGE_REFRESH_DELAY_MS = 5_000;
const pendingPostUsageRefreshes = new Set<string>();
function isRecord(value: unknown): value is JsonRecord {
return value !== null && typeof value === "object" && !Array.isArray(value);
}
function toProviderLimitsCacheEntry(
usage: JsonRecord,
source: SyncSource,
@@ -135,67 +132,6 @@ export function notifyProviderUsageRecorded(
// the provider-limits route and the background auto-sync scheduler at server boot.
onUsageRecorded(notifyProviderUsageRecorded);
function isUsageQuotaKeyAllowed(provider: string, quotaKey: string): boolean {
if (quotaKey === "credits" || quotaKey === "models") return true;
if (provider === "antigravity") return isUserCallableAntigravityModelId(quotaKey);
if (provider === "agy") return isUserCallableAgyModelId(quotaKey);
return true;
}
function normalizeUsageQuotaKey(provider: string, quotaKey: string): string | null {
if (quotaKey === "credits" || quotaKey === "models") return quotaKey;
if (provider === "antigravity" || provider === "agy") {
const clientKey = toClientAntigravityModelId(quotaKey);
return isUsageQuotaKeyAllowed(provider, clientKey) ? clientKey : null;
}
return isUsageQuotaKeyAllowed(provider, quotaKey) ? quotaKey : null;
}
function normalizeUsageQuotasForProvider(
provider: string,
quotas: JsonRecord | null | undefined
): JsonRecord | null {
if (!isRecord(quotas)) return quotas ?? null;
const normalized: JsonRecord = {};
let changed = false;
for (const [quotaKey, quota] of Object.entries(quotas)) {
const normalizedKey = normalizeUsageQuotaKey(provider, quotaKey);
if (!normalizedKey) {
changed = true;
continue;
}
const existing = normalized[normalizedKey];
if (existing && isRecord(existing) && isRecord(quota)) {
const existingSource = String(existing.quotaSource ?? "");
const nextSource = String(quota.quotaSource ?? "");
const sourceRank: Record<string, number> = {
fetchAvailableModels: 0,
localUsageHistory: 1,
retrieveUserQuota: 2,
};
if ((sourceRank[existingSource] ?? 0) > (sourceRank[nextSource] ?? 0)) {
continue;
}
}
normalized[normalizedKey] = quota as JsonRecord;
if (normalizedKey !== quotaKey) changed = true;
}
return changed ? normalized : quotas;
}
function sanitizeUsageQuotasForProvider(provider: string, usage: JsonRecord): JsonRecord {
if (provider !== "antigravity" && provider !== "agy") return usage;
if (!isRecord(usage.quotas)) return usage;
const sanitizedQuotas = normalizeUsageQuotasForProvider(provider, usage.quotas);
return sanitizedQuotas === usage.quotas ? usage : { ...usage, quotas: sanitizedQuotas };
}
function hasRetrieveUserQuotaSource(
provider: string,
cache: ProviderLimitsCacheEntry | undefined

View File

@@ -0,0 +1,72 @@
import {
isUserCallableAntigravityModelId,
toClientAntigravityModelId,
} from "@omniroute/open-sse/config/antigravityModelAliases.ts";
import { isUserCallableAgyModelId } from "@omniroute/open-sse/config/agyModels.ts";
type JsonRecord = Record<string, unknown>;
export function isRecord(value: unknown): value is JsonRecord {
return value !== null && typeof value === "object" && !Array.isArray(value);
}
export function isUsageQuotaKeyAllowed(provider: string, quotaKey: string): boolean {
if (quotaKey === "credits" || quotaKey === "models") return true;
if (provider === "antigravity") return isUserCallableAntigravityModelId(quotaKey);
if (provider === "agy") return isUserCallableAgyModelId(quotaKey);
return true;
}
export function normalizeUsageQuotaKey(provider: string, quotaKey: string): string | null {
if (quotaKey === "credits" || quotaKey === "models") return quotaKey;
if (provider === "antigravity" || provider === "agy") {
const clientKey = toClientAntigravityModelId(quotaKey);
return isUsageQuotaKeyAllowed(provider, clientKey) ? clientKey : null;
}
return isUsageQuotaKeyAllowed(provider, quotaKey) ? quotaKey : null;
}
export function normalizeUsageQuotasForProvider(
provider: string,
quotas: JsonRecord | null | undefined
): JsonRecord | null {
if (!isRecord(quotas)) return quotas ?? null;
const normalized: JsonRecord = {};
let changed = false;
for (const [quotaKey, quota] of Object.entries(quotas)) {
const normalizedKey = normalizeUsageQuotaKey(provider, quotaKey);
if (!normalizedKey) {
changed = true;
continue;
}
const existing = normalized[normalizedKey];
if (existing && isRecord(existing) && isRecord(quota)) {
const existingSource = String(existing.quotaSource ?? "");
const nextSource = String(quota.quotaSource ?? "");
const sourceRank: Record<string, number> = {
fetchAvailableModels: 0,
localUsageHistory: 1,
retrieveUserQuota: 2,
};
if ((sourceRank[existingSource] ?? 0) > (sourceRank[nextSource] ?? 0)) {
continue;
}
}
normalized[normalizedKey] = quota as JsonRecord;
if (normalizedKey !== quotaKey) changed = true;
}
return changed ? normalized : quotas;
}
export function sanitizeUsageQuotasForProvider(provider: string, usage: JsonRecord): JsonRecord {
if (provider !== "antigravity" && provider !== "agy") return usage;
if (!isRecord(usage.quotas)) return usage;
const sanitizedQuotas = normalizeUsageQuotasForProvider(provider, usage.quotas);
return sanitizedQuotas === usage.quotas ? usage : { ...usage, quotas: sanitizedQuotas };
}

View File

@@ -0,0 +1,104 @@
/**
* Characterization + API-surface test: providerLimits.ts god-file decomposition.
*
* The pure quota-key/quota-value normalization helpers (+ the isRecord type
* guard they share) were extracted verbatim from src/lib/usage/providerLimits.ts
* into the self-contained leaf src/lib/usage/providerLimits/quotaNormalize.ts
* (no DB, no network — the leaf does NOT import the host, so no cycle). The sync
* orchestration / DB / network code stays in the host.
*
* Verifies that:
* 1. isRecord + isUsageQuotaKeyAllowed behave correctly (DB-free).
* 2. The host providerLimits.ts still exposes the FULL public API (13 funcs).
* 3. The quotaNormalize leaf exports its helpers directly.
*
* Deeper quota-sanitization behaviour is covered by the existing
* provider-limits-sanitize-scope-3821 / db-provider-limits suites; this test
* pins the extraction boundary + the simplest pure branches.
*/
import { describe, it } from "node:test";
import assert from "node:assert/strict";
import {
isRecord,
isUsageQuotaKeyAllowed,
normalizeUsageQuotasForProvider,
sanitizeUsageQuotasForProvider,
} from "../../src/lib/usage/providerLimits/quotaNormalize.ts";
describe("providerLimits/quotaNormalize — isRecord", () => {
it("is true only for plain non-null, non-array objects", () => {
assert.equal(isRecord({ a: 1 }), true);
assert.equal(isRecord({}), true);
assert.equal(isRecord(null), false);
assert.equal(isRecord([1, 2]), false);
assert.equal(isRecord("x"), false);
assert.equal(isRecord(5), false);
});
});
describe("providerLimits/quotaNormalize — isUsageQuotaKeyAllowed", () => {
it("always allows the generic 'credits' and 'models' keys", () => {
assert.equal(isUsageQuotaKeyAllowed("openai", "credits"), true);
assert.equal(isUsageQuotaKeyAllowed("anthropic", "models"), true);
assert.equal(isUsageQuotaKeyAllowed("antigravity", "credits"), true);
});
});
describe("providerLimits/quotaNormalize — sanitize/normalize are callable & pure-shaped", () => {
it("sanitizeUsageQuotasForProvider returns a record (no throw on a plain usage object)", () => {
const usage = { quotas: { credits: { used: 1, limit: 10 } } };
const out = sanitizeUsageQuotasForProvider("openai", usage);
assert.equal(isRecord(out), true);
});
it("normalizeUsageQuotasForProvider is exported and callable", () => {
assert.equal(typeof normalizeUsageQuotasForProvider, "function");
});
});
// ── host public API surface ──────────────────────────────────────────────────
const host = await import("../../src/lib/usage/providerLimits.ts");
describe("providerLimits.ts public API surface (13 functions)", () => {
const expected = [
"fetchAndPersistProviderLimits",
"fetchLiveProviderLimits",
"getCachedProviderLimitsMap",
"getLastProviderLimitsAutoSyncTime",
"getProviderLimitsSyncIntervalMinutes",
"getProviderLimitsSyncIntervalMs",
"getProviderLimitsSyncSpacingMs",
"getSanitizedCachedProviderLimitsMap",
"notifyProviderUsageRecorded",
"quotaPathShouldMarkExpired",
"refreshAndUpdateCredentials",
"shouldAttemptRotatingRefresh",
"syncAllProviderLimits",
];
for (const name of expected) {
it(`exposes ${name} as a function`, () => {
assert.equal(typeof host[name], "function", `${name} must be a function on the host`);
});
}
it("loses no public function in the split", () => {
const missing = expected.filter((n) => typeof host[n] !== "function");
assert.deepEqual(missing, [], `missing: ${missing.join(", ")}`);
});
});
describe("quotaNormalize.ts exports its helpers directly", () => {
it("the moved helpers are functions on the leaf", async () => {
const qn = await import("../../src/lib/usage/providerLimits/quotaNormalize.ts");
for (const fn of [
"isRecord",
"isUsageQuotaKeyAllowed",
"normalizeUsageQuotaKey",
"normalizeUsageQuotasForProvider",
"sanitizeUsageQuotasForProvider",
]) {
assert.equal(typeof qn[fn], "function", fn);
}
});
});