fix(quota): block per-key overage for countable units (real pool-total consumed)

Replace the saturation-signal approximation (globalUsedPercent × effectiveLimit,
which is always 0 for requests/tokens/usd) with store.poolConsumedTotal() so
the pool actually saturates and enforceQuotaShare returns "block" when the pool
total hits the effective limit for countable dimensions.

"percent" dimensions continue to use the upstream saturation signal, which is
the authoritative measure for provider-reported utilisation windows.
This commit is contained in:
diegosouzapw
2026-05-31 18:15:11 -03:00
parent abb77879db
commit ddd129f3f9
2 changed files with 194 additions and 3 deletions

View File

@@ -28,6 +28,22 @@ import { listAllocationsForApiKey, getPool } from "@/lib/db/quotaPools";
const SATURATION_THRESHOLD = Number(process.env.QUOTA_SATURATION_THRESHOLD ?? "0.5");
/**
* Units for which the store tracks a real pool-wide aggregate (sum of per-key
* consumption via quota_consumption rows). For these units, globalUsedPercent
* (the saturation signal from the upstream provider) is always 0 because no
* external API reports a "percent used" for raw request/token/usd counters.
*
* Using globalUsedPercent × effectiveLimit for countable units would always
* yield consumedTotal = 0, meaning the pool never saturates and per-key
* overage is never blocked. We use store.poolConsumedTotal() instead, which
* sums the actual consumption across all keys in the pool window.
*
* "percent" dimensions remain driven by the saturation signal because that IS
* the authoritative consumption measure (the upstream provider percentage).
*/
const COUNTABLE_UNITS = new Set(["requests", "tokens", "usd"]);
// ---------------------------------------------------------------------------
// Public API
// ---------------------------------------------------------------------------
@@ -128,9 +144,21 @@ export async function enforceQuotaShare(input: EnforceInput): Promise<EnforceDec
// This is the summed budget: N accounts contribute N × L capacity to the shared bucket.
const effectiveLimit = dim.limit * accountCount;
// v1 pragmatic approximation: consumedTotal = globalUsedPercent * effectiveLimit.
// (Exact aggregate by pool is delivered by F8's /api/quota/pools/[id]/usage endpoint.)
const consumedTotal = globalUsedPercent * effectiveLimit;
// Derive consumedTotal based on the unit type:
// - Countable units (requests/tokens/usd): use the real store aggregate so the
// pool can actually saturate and block per-key overage. The saturation signal
// (globalUsedPercent) is always 0 for these units — using it would permanently
// keep consumedTotal at 0 and never trigger the block path.
// - percent dimensions: the saturation signal IS the consumed signal (the upstream
// provider returns a utilisation percentage, not raw counts).
let consumedTotal: number;
if (COUNTABLE_UNITS.has(dim.unit)) {
// Real pool-wide aggregate (sum of per-key consumption across all apiKeyIds).
consumedTotal = await store.poolConsumedTotal(pool.id, dimKey).catch(() => 0);
} else {
// percent (account-quota window): the saturation signal is authoritative.
consumedTotal = globalUsedPercent * effectiveLimit;
}
dimensionsInfo.push({
key: dimKey,