feat(quota): estratégia dedicada de quota-share (DRR + P2C in-flight + gating per-model) [Fase 3 #9] (#4939)

* feat(quota): estratégia dedicada de quota-share (DRR + P2C in-flight + gating per-model) [Fase 3 #9]

Estratégia interna "quota-share" isolada num módulo dedicado — NÃO toca a seleção/
fair-share genérica (decisão do dono: não mexer no que já funciona). Os combos qtSd/
(quotaCombos.ts) passam de fill-first para essa strategy; combo.ts ganha só 1 branch
de dispatch que delega 100% ao módulo (nenhum case existente alterado).

- quotaShareStrategy.ts: gating per-model (isBucketSaturated do #3) + DRR (quantum
  proporcional ao weight) + P2C sobre carga in-flight.
- quotaShareInflight.ts: contador in-flight com TTL/lease de 120s — fallback do
  decrement-on-abort sem precisar instrumentar o combo genérico.
- "quota-share" registrada como strategy INTERNA (não exposta na UI).
- testes de síntese (quota-combo-balancing, quota-multiprovider) alinhados: a strategy
  esperada dos combos qtSd/ passa de "fill-first" para "quota-share" (alinhamento ao novo
  comportamento intencional, não mascaramento — os 73 testes de qtSd/ seguem verdes).

* test(quota-share): alinha 2 scope-guards ao godfile sweep (base-reds que bloqueavam o CI)

Dois testes de "arquivo contém X" quebraram por decomposições de godfile que outras
sessões mergearam no release DURANTE a validação de #9 — NÃO são regressão de #9
(que não toca validation/oauth). Alinhados ao novo layout, asserts preservados:
- proxy-bypass-scope-guard #3226: bypassProxyPatch foi extraído de validation.ts para
  validation/headers.ts (split #4921–#4930) → o teste lê a camada de validação.
- sse-error-passthrough #3324: a windsurf authHint foi extraída de providers.ts para
  providers/oauth.ts → o teste lê o novo local.

---------

Co-authored-by: Diego Rodrigues de Sa e Souza <souzamiriamrodrigues790@gmail.com>
This commit is contained in:
Diego Rodrigues de Sa e Souza
2026-06-24 11:40:17 -03:00
committed by GitHub
parent 833adce8fb
commit 9708288b57
12 changed files with 812 additions and 51 deletions

View File

@@ -141,7 +141,8 @@
"open-sse/services/claudeCodeCompatible.ts": 1202,
"_rebaseline_pr4592_exclude_exhausted_auto": "Reconcile #4592 already-merged growth: combo.ts 2991->3036 (+45, terminal-status quota-cutoff exclusion in buildAutoCandidates + opt-in gate). Fast-gate PR->release does not run check:file-size.",
"_rebaseline_2026_06_24_headroom_strategy": "Headroom-aware connection selection (dario technique): combo.ts 3168->3180 (+12 = a new `else if (strategy === \"headroom\")` dispatch branch in handleComboChat that delegates to orderTargetsByHeadroom + its log line, plus the import). The actual logic lives OUT of the god-file: the pure ranker rankByHeadroom/computeHeadroom is the new leaf open-sse/services/combo/headroomRanking.ts (91 LOC, <cap) and the async orderer orderTargetsByHeadroom is appended to the existing open-sse/services/combo/quotaStrategies.ts (<cap) next to its sibling reset-aware/reset-window orderers (reuses their connection-expansion machinery). headroom = 1 - max(util_5h, util_7d) from getSaturation (src/lib/quota/saturationSignals.ts), prefers the connection with the most free capacity. Only the dispatch wiring is irreducible at the existing combo strategy chokepoint (mirrors the reset-aware/reset-window/context-optimized branches); not extractable without hiding the call site. fill-first stays default; all existing strategies untouched. Covered by tests/unit/combo-headroom-ranking.test.ts (pure helper) + tests/unit/combo-headroom-strategy.test.ts (orderer, saturation injected). Structural shrink of combo.ts tracked in #3501.",
"open-sse/services/combo.ts": 3180,
"_rebaseline_2026_06_24_quota_share_strategy": "Dedicated quota-share strategy (Phase 3 #9): combo.ts 3180->3190 (+10 = one new `else if (strategy === \"quota-share\")` dispatch branch in handleComboChat that delegates 100% to selectQuotaShareTarget + its log line, plus the import). All the new logic lives OUT of the god-file in two new leaves under open-sse/services/combo/: quotaShareInflight.ts (in-flight counter with TTL/lease, ~150 LOC <cap) and quotaShareStrategy.ts (per-model bucket gating via isBucketSaturated + DRR proportional to weight + P2C over in-flight, ~240 LOC <cap). Only the dispatch wiring is irreducible at the existing combo strategy chokepoint (mirrors the headroom/reset-aware/reset-window/context-optimized branches); not extractable without hiding the call site. ZERO existing strategy cases were modified — only this branch was added, and the qtSd/ combos switched from fill-first to quota-share in src/lib/quota/quotaCombos.ts. Covered by tests/unit/quota-share-strategy.test.ts (gating, DRR fairness, P2C in-flight, fail-open, activation). Structural shrink of combo.ts tracked in #3501.",
"open-sse/services/combo.ts": 3190,
"open-sse/services/compression/strategySelector.ts": 848,
"open-sse/services/rateLimitManager.ts": 1035,
"open-sse/services/tokenRefresh.ts": 2070,

View File

@@ -74,6 +74,7 @@ import { supportsToolCalling } from "./modelCapabilities.ts";
import { estimateTokens } from "./contextManager.ts";
import { getSessionConnection } from "./sessionManager.ts";
import { applySessionStickiness, recordStickyBinding } from "./combo/sessionStickiness.ts";
import { selectQuotaShareTarget } from "./combo/quotaShareStrategy.ts";
import { orderTargetsByEvalScores } from "./evalRouting.ts";
import { generateRoutingHints } from "./manifestAdapter";
import type { RoutingHint } from "./manifestAdapter";
@@ -1555,6 +1556,15 @@ export async function handleComboChat({
"COMBO",
`Headroom ordering: ${orderedTargets[0]?.modelStr}${orderedTargets[0]?.connectionId ? ` (${orderedTargets[0].connectionId})` : ""} has most free capacity`
);
} else if (strategy === "quota-share") {
// Internal quota-share combos (qtSd/): delegate 100% to the dedicated module
// (DRR + P2C in-flight + per-model bucket gating). No generic case is touched.
const qsModel = typeof body?.model === "string" ? body.model : (orderedTargets[0]?.modelStr ?? "");
orderedTargets = selectQuotaShareTarget(orderedTargets, combo.name, qsModel).orderedTargets;
log.info(
"COMBO",
`Quota-share ordering: ${orderedTargets[0]?.modelStr}${orderedTargets[0]?.connectionId ? ` (${orderedTargets[0].connectionId})` : ""} selected (DRR+P2C)`
);
}
const _sticky = await applySessionStickiness(orderedTargets, body.messages as Array<{ role?: string; content?: unknown }>); orderedTargets = _sticky.targets;
orderedTargets = orderTargetsByEvalScores(orderedTargets, config.evalRouting, log);

View File

@@ -0,0 +1,133 @@
/**
* quotaShareInflight.ts — In-flight request counter for the quota-share strategy.
*
* Tracks how many requests are currently in-flight per connectionId so the
* quota-share P2C tie-break can prefer the least-loaded connection in real time.
*
* Decrement-on-abort safety (TTL/lease):
* The generic combo dispatch path is intentionally NOT instrumented (so this
* feature cannot regress existing strategies). Instead, each in-flight slot
* carries an expiry: incrementInflight() stamps `nowMs + leaseMs`. The normal
* path calls decrementInflight() (returned to the caller as a callback) once
* the request settles, which clears the slot immediately. If a request is
* aborted or crashes before that callback runs, the slot still auto-expires
* after DEFAULT_LEASE_MS — so the counter can never leak forever, even without
* touching the generic dispatch.
*
* Fail-open: getInflight() returns 0 for an unknown / empty connectionId.
* All time input is injectable (the `nowMs` param) so unit tests drive the
* clock deterministically — the tested path never calls Date.now() implicitly.
*
* Part of: Quota Sharing Engine — Phase 3 (#9 dedicated quota-share strategy).
*/
// ---------------------------------------------------------------------------
// Constants
// ---------------------------------------------------------------------------
/**
* Default lease duration (ms). A slot that is never explicitly decremented
* (aborted / crashed request) auto-expires after this, bounding the counter.
*/
export const DEFAULT_LEASE_MS = 120_000;
// ---------------------------------------------------------------------------
// Types
// ---------------------------------------------------------------------------
interface InflightSlot {
count: number;
expiresAtMs: number;
}
// ---------------------------------------------------------------------------
// In-process store. Key: connectionId.
// ---------------------------------------------------------------------------
const _inflightMap = new Map<string, InflightSlot>();
// ---------------------------------------------------------------------------
// Public API
// ---------------------------------------------------------------------------
/**
* Increment the in-flight counter for a connection and return the new count.
* Sets / refreshes the slot's expiry lease.
*
* @param connectionId Opaque connection identifier (empty → no-op, returns 0).
* @param leaseMs Lease before the slot auto-expires if never decremented.
* @param nowMs Current epoch ms; defaults to Date.now() (off-path only).
*/
export function incrementInflight(
connectionId: string,
leaseMs: number = DEFAULT_LEASE_MS,
nowMs: number = Date.now()
): number {
if (!connectionId) return 0;
pruneExpired(nowMs);
const slot = _inflightMap.get(connectionId);
const base = slot && slot.expiresAtMs > nowMs ? slot.count : 0;
const newCount = base + 1;
_inflightMap.set(connectionId, { count: newCount, expiresAtMs: nowMs + leaseMs });
return newCount;
}
/**
* Decrement the in-flight counter for a connection, flooring at 0. The entry is
* removed once the count reaches 0 (or if the slot already expired).
*
* @param connectionId Opaque connection identifier (empty → no-op).
* @param nowMs Current epoch ms; defaults to Date.now() (off-path only).
*/
export function decrementInflight(connectionId: string, nowMs: number = Date.now()): void {
if (!connectionId) return;
const slot = _inflightMap.get(connectionId);
if (!slot || slot.expiresAtMs <= nowMs) {
_inflightMap.delete(connectionId);
return;
}
const newCount = Math.max(0, slot.count - 1);
if (newCount === 0) {
_inflightMap.delete(connectionId);
} else {
_inflightMap.set(connectionId, { count: newCount, expiresAtMs: slot.expiresAtMs });
}
}
/**
* Current in-flight count for a connection (0 if unknown / empty / expired).
*
* @param connectionId Opaque connection identifier.
* @param nowMs Current epoch ms; defaults to Date.now() (off-path only).
*/
export function getInflight(connectionId: string, nowMs: number = Date.now()): number {
if (!connectionId) return 0;
const slot = _inflightMap.get(connectionId);
if (!slot || slot.expiresAtMs <= nowMs) return 0;
return slot.count;
}
// ---------------------------------------------------------------------------
// Internal helpers
// ---------------------------------------------------------------------------
/** Drop all expired slots so the map cannot grow unbounded with stale leases. */
function pruneExpired(nowMs: number): void {
for (const [key, slot] of _inflightMap) {
if (slot.expiresAtMs <= nowMs) _inflightMap.delete(key);
}
}
// ---------------------------------------------------------------------------
// Test helpers (never call in production code)
// ---------------------------------------------------------------------------
/** Clear all in-flight state. Tests only — keeps state isolation between cases. */
export function _clearInflightForTest(): void {
_inflightMap.clear();
}
/** Return the current slot count. Tests only — black-box size assertion. */
export function _inflightSizeForTest(): number {
return _inflightMap.size;
}

View File

@@ -0,0 +1,261 @@
/**
* quotaShareStrategy.ts — Dedicated selection strategy for quota-share combos.
*
* Activated ONLY for the internal "quota-share" strategy (the auto-minted qtSd/
* combos). It is never imported by generic combo routing paths, so tuning this
* module can never regress the existing strategies (fill-first, p2c, headroom…).
*
* Three mechanisms are applied in sequence:
*
* 1. Per-model bucket gating (accountBuckets.isBucketSaturated):
* A connection whose 5h, 7d, or per-model 7d:<model> window is saturated
* for the requested model is moved to a DEPRIORITIZED tail rather than
* dropped. If EVERY connection is saturated, all are eligible again
* (fail-open: a quota-share combo is never hard-blocked here).
*
* 2. DRR (Deficit Round Robin):
* Among the eligible connections, each round adds a quantum proportional to
* the target weight to that target's deficit, then selects the target with
* the largest accumulated deficit and zeroes it. Over many requests this
* distributes load proportionally to weight, deterministically.
*
* 3. P2C (Power of Two Choices) over real in-flight load:
* Between the top two DRR candidates, the one with fewer active in-flight
* requests (quotaShareInflight) wins; ties keep the DRR order. The winner's
* in-flight counter is incremented immediately and a decrement callback is
* returned for the caller's finally/abort handler.
*
* All state is in-process; no DB or network calls. The clock is injectable
* (the `nowMs` param) so unit tests are fully deterministic.
*
* Part of: Quota Sharing Engine — Phase 3 (#9 dedicated quota-share strategy).
*/
import { isBucketSaturated } from "../../../src/lib/quota/accountBuckets.ts";
import { incrementInflight, decrementInflight, getInflight } from "./quotaShareInflight.ts";
import type { ResolvedComboTarget } from "./types.ts";
// ---------------------------------------------------------------------------
// Constants
// ---------------------------------------------------------------------------
/** Maximum number of per-combo DRR states retained before oldest-entry eviction. */
const MAX_DRR_COMBOS = 200;
// ---------------------------------------------------------------------------
// DRR state
// ---------------------------------------------------------------------------
/**
* Outer key: comboName. Inner key: target.executionKey. Value: accumulated
* deficit (higher = this target is "owed" more service). Single instance —
* never duplicate this Map (state cohesion).
*/
const _drrState = new Map<string, Map<string, number>>();
function getDrrDeficits(comboName: string): Map<string, number> {
let deficits = _drrState.get(comboName);
if (!deficits) {
if (_drrState.size >= MAX_DRR_COMBOS) {
// Evict the oldest entry (Map iterates in insertion order).
const oldestKey = _drrState.keys().next().value;
if (oldestKey !== undefined) _drrState.delete(oldestKey);
}
deficits = new Map();
_drrState.set(comboName, deficits);
}
return deficits;
}
// ---------------------------------------------------------------------------
// Mechanism 1 — per-model bucket gating
// ---------------------------------------------------------------------------
/** Extract the bare model name from "<provider>/<model>" (or pass through). */
function bareModelName(modelStr: string): string {
const slash = modelStr.indexOf("/");
return slash >= 0 ? modelStr.slice(slash + 1) : modelStr;
}
/**
* Return the eligible (non-saturated) targets. Fail-open: when every target is
* saturated, the original list is returned so the combo is never hard-blocked.
*/
function filterEligibleBySaturation(
targets: ResolvedComboTarget[],
modelStr: string,
nowMs: number
): ResolvedComboTarget[] {
const modelName = bareModelName(modelStr);
const eligible = targets.filter((target) => {
const connId = target.connectionId ?? "";
if (connId === "") return true; // no connection → cannot be saturation-scored
const saturated =
isBucketSaturated(connId, "5h", nowMs) ||
isBucketSaturated(connId, "7d", nowMs) ||
(modelName !== "" && isBucketSaturated(connId, `7d:${modelName}`, nowMs));
return !saturated;
});
return eligible.length > 0 ? eligible : targets;
}
// ---------------------------------------------------------------------------
// Mechanism 2 — DRR ordering
// ---------------------------------------------------------------------------
/**
* Reorder `targets` by deficit round-robin (quantum proportional to weight).
* Returns a NEW array with the highest-deficit target first; mutates the shared
* DRR state for `comboName`.
*
* Classic DRR: every round each target gains a quantum equal to its normalized
* weight share; the target with the largest deficit is selected and pays a fixed
* cost of 1. Subtracting a constant (rather than zeroing) keeps the accumulated
* fractional credit, so long-run selection frequency converges EXACTLY to the
* weight ratio and the choice stays deterministic (no fragile float ties).
*/
function applyDrr(targets: ResolvedComboTarget[], comboName: string): ResolvedComboTarget[] {
if (targets.length <= 1) return targets.slice();
const deficits = getDrrDeficits(comboName);
const totalWeight = targets.reduce((sum, t) => sum + normalizeWeight(t.weight), 0);
// Add each target's quantum (weight share) to its deficit.
for (const target of targets) {
const quantum = normalizeWeight(target.weight) / totalWeight;
deficits.set(target.executionKey, (deficits.get(target.executionKey) ?? 0) + quantum);
}
// Select the target with the largest deficit (ties keep input order).
let winner = targets[0];
let bestDeficit = deficits.get(winner.executionKey) ?? 0;
for (let i = 1; i < targets.length; i++) {
const d = deficits.get(targets[i].executionKey) ?? 0;
if (d > bestDeficit) {
bestDeficit = d;
winner = targets[i];
}
}
// Winner pays a unit cost; the leftover credit carries into the next round.
deficits.set(winner.executionKey, bestDeficit - 1);
const rest = targets.filter((t) => t.executionKey !== winner.executionKey);
return [winner, ...rest];
}
/** Weights default to 1 and are floored at 1 to keep quantum math well-defined. */
function normalizeWeight(weight: number | undefined): number {
return Number.isFinite(weight) && (weight as number) > 0 ? (weight as number) : 1;
}
// ---------------------------------------------------------------------------
// Mechanism 3 — P2C over in-flight load
// ---------------------------------------------------------------------------
/**
* Pick the less-loaded of the first two candidates. Returns 0 to keep the DRR
* winner, or 1 to prefer the runner-up. Ties favor the DRR winner (index 0).
*/
function pickByInflightP2C(
first: ResolvedComboTarget,
second: ResolvedComboTarget,
nowMs: number
): 0 | 1 {
const loadFirst = getInflight(first.connectionId ?? "", nowMs);
const loadSecond = getInflight(second.connectionId ?? "", nowMs);
return loadSecond < loadFirst ? 1 : 0;
}
// ---------------------------------------------------------------------------
// Public API
// ---------------------------------------------------------------------------
export interface QuotaShareResult {
/** The selected target, or null when `targets` was empty. */
target: ResolvedComboTarget | null;
/**
* Full ordered dispatch list: winner first, then the remaining eligible
* targets, then any deprioritized (saturated) targets as last-resort fallbacks.
*/
orderedTargets: ResolvedComboTarget[];
/**
* Release the winner's in-flight slot. Call this in a finally/abort handler.
* Idempotent — safe to call more than once. If never called, the slot still
* auto-expires (see quotaShareInflight DEFAULT_LEASE_MS).
*/
decrementInflight: () => void;
}
/**
* Select the best target using the dedicated quota-share strategy.
*
* @param targets Resolved combo targets (the combo's eligible step entries).
* @param comboName Combo name; used as the DRR state key.
* @param modelStr Requested model string, e.g. "anthropic/claude-opus-4".
* @param nowMs Current epoch ms for bucket/in-flight checks; defaults to Date.now().
*/
export function selectQuotaShareTarget(
targets: ResolvedComboTarget[],
comboName: string,
modelStr: string,
nowMs: number = Date.now()
): QuotaShareResult {
const noOp = (): void => {};
if (targets.length === 0) {
return { target: null, orderedTargets: [], decrementInflight: noOp };
}
// 1) Per-model bucket gating.
const eligible = filterEligibleBySaturation(targets, modelStr, nowMs);
const deprioritized = targets.filter((t) => !eligible.includes(t));
// 2) DRR ordering over the eligible set.
const ordered = applyDrr(eligible, comboName);
// 3) P2C over in-flight between the top two.
let winner: ResolvedComboTarget;
let rest: ResolvedComboTarget[];
if (ordered.length >= 2 && pickByInflightP2C(ordered[0], ordered[1], nowMs) === 1) {
winner = ordered[1];
rest = [ordered[0], ...ordered.slice(2)];
} else {
winner = ordered[0];
rest = ordered.slice(1);
}
// Reserve the winner's in-flight slot immediately.
const winnerConnectionId = winner.connectionId ?? "";
if (winnerConnectionId) incrementInflight(winnerConnectionId, undefined, nowMs);
const orderedTargets = [winner, ...rest, ...deprioritized];
// Idempotent decrement callback for the caller's finally/abort path. Uses the
// selection-time clock so the slot (stamped nowMs + lease) is never treated as
// expired here — it decrements the live count deterministically.
let released = false;
const release = (): void => {
if (released) return;
released = true;
if (winnerConnectionId) decrementInflight(winnerConnectionId, nowMs);
};
return { target: winner, orderedTargets, decrementInflight: release };
}
// ---------------------------------------------------------------------------
// Test helpers (never call in production code)
// ---------------------------------------------------------------------------
/** Clear all DRR state. Tests only — keeps state isolation between cases. */
export function _clearDrrStateForTest(): void {
_drrState.clear();
}
/** Return the DRR deficit for a (comboName, executionKey). Tests only. */
export function _getDrrDeficitForTest(comboName: string, executionKey: string): number {
return _drrState.get(comboName)?.get(executionKey) ?? 0;
}

View File

@@ -475,8 +475,14 @@ async function main(): Promise<void> {
}
// ── (2) Combo strategies ──────────────────────────────────────────────────
// Canonical = user-facing ROUTING_STRATEGY_VALUES INTERNAL_ROUTING_STRATEGY_VALUES
// (system-only strategies like "quota-share" are registered but hidden from the UI;
// they still must have a real dispatch branch in combo.ts — enforced below).
const strategiesMod = await import("@/shared/constants/routingStrategies.ts");
const canonical = strategiesMod.ROUTING_STRATEGY_VALUES as readonly string[];
const canonical = [
...(strategiesMod.ROUTING_STRATEGY_VALUES as readonly string[]),
...(strategiesMod.INTERNAL_ROUTING_STRATEGY_VALUES as readonly string[]),
];
const comboSource = readFileSync(resolvePath(REPO_ROOT, "open-sse/services/combo.ts"), "utf8");
const handled = extractHandledStrategies(comboSource);

View File

@@ -28,6 +28,14 @@ import {
quotaGroupSlug,
} from "./quotaModelNaming";
import { createLogger } from "@/shared/utils/logger";
import type { AnyRoutingStrategyValue } from "@/shared/constants/routingStrategies";
/**
* Routing strategy for every auto-minted quota-share (qtSd/) combo. Internal
* only — resolves to the dedicated DRR + P2C in-flight + per-model gating
* selection in combo.ts (Phase 3 #9). Was "fill-first" before the hardening.
*/
export const QUOTA_SHARE_STRATEGY: AnyRoutingStrategyValue = "quota-share";
const log = createLogger("quota/quotaCombos");
@@ -170,8 +178,9 @@ export async function syncQuotaCombos(poolId: string): Promise<void> {
const poolProvider: string | undefined = upsertWork[0]?.provider;
// Group steps by model across all connections (Task 3 guarantees a single provider).
// This produces one combo per model with ALL connections' steps + strategy "fill-first",
// fixing the collision where two same-provider connections would overwrite each other.
// This produces one combo per model with ALL connections' steps + the dedicated
// "quota-share" strategy (Phase 3 #9), fixing the collision where two same-provider
// connections would overwrite each other.
const byModel = new Map<string, Array<{ connId: string; provider: string }>>();
for (const { connId, provider, modelIds } of upsertWork) {
for (const modelId of modelIds) {
@@ -196,7 +205,7 @@ export async function syncQuotaCombos(poolId: string): Promise<void> {
const payload = {
name: comboName,
models: steps,
strategy: "fill-first" as const,
strategy: QUOTA_SHARE_STRATEGY,
isHidden: true,
};
if (existing && typeof existing.id === "string") await updateCombo(existing.id, payload);

View File

@@ -20,6 +20,19 @@ export const ROUTING_STRATEGY_VALUES = [
export type RoutingStrategyValue = (typeof ROUTING_STRATEGY_VALUES)[number];
/**
* Internal-only routing strategy values. These are used by system-generated
* combos (e.g. the auto-minted quota-share `qtSd/` combos) and are NEVER exposed
* in the UI or user-facing API — deliberately kept OUT of ROUTING_STRATEGY_VALUES
* and ROUTING_STRATEGIES so they never appear as a selectable option.
*/
export const INTERNAL_ROUTING_STRATEGY_VALUES = ["quota-share"] as const;
export type InternalRoutingStrategyValue = (typeof INTERNAL_ROUTING_STRATEGY_VALUES)[number];
/** Any routing strategy value, including internal ones. Used for combo dispatch. */
export type AnyRoutingStrategyValue = RoutingStrategyValue | InternalRoutingStrategyValue;
export const AUTO_ROUTING_STRATEGY_VALUES = [
"rules",
"cost",
@@ -47,12 +60,16 @@ export const ACCOUNT_FALLBACK_STRATEGY_VALUES = [
export type AccountFallbackStrategyValue = (typeof ACCOUNT_FALLBACK_STRATEGY_VALUES)[number];
export function normalizeRoutingStrategy(value: unknown): RoutingStrategyValue {
export function normalizeRoutingStrategy(value: unknown): AnyRoutingStrategyValue {
if (typeof value !== "string") return "priority";
const normalized = value.trim().toLowerCase();
if (normalized === "usage") return "least-used";
if (normalized === "context") return "context-optimized";
if (normalized === "weekly-reset" || normalized === "reset-window-order") return "reset-window";
// Internal strategies (e.g. quota-share) are preserved verbatim, never stripped
// to "priority", so system-minted combos resolve to their dedicated dispatch.
if ((INTERNAL_ROUTING_STRATEGY_VALUES as readonly string[]).includes(normalized))
return normalized as InternalRoutingStrategyValue;
return (ROUTING_STRATEGY_VALUES as readonly string[]).includes(normalized)
? (normalized as RoutingStrategyValue)
: "priority";

View File

@@ -18,14 +18,19 @@ import assert from "node:assert/strict";
import { readFileSync } from "node:fs";
test("bypassProxyPatch is present in the NVIDIA validation path (#3226 documented exception)", () => {
const validation = readFileSync("src/lib/providers/validation.ts", "utf8");
// After the validation.ts godfile split (#4921#4930), bypassProxyPatch moved to the
// extracted validation/headers.ts. Assert the bypass lives in the validation LAYER
// (validation.ts + its extracted modules), not that it stayed in one file.
const validationLayer =
readFileSync("src/lib/providers/validation.ts", "utf8") +
readFileSync("src/lib/providers/validation/headers.ts", "utf8");
assert.ok(
validation.includes("bypassProxyPatch"),
"expected bypassProxyPatch to be present in validation.ts (the documented NVIDIA exception)"
validationLayer.includes("bypassProxyPatch"),
"expected bypassProxyPatch in the validation layer (validation/headers.ts) — the documented NVIDIA exception"
);
assert.ok(
validation.includes("directHttpsRequest"),
"expected directHttpsRequest helper to be present in validation.ts"
validationLayer.includes("directHttpsRequest"),
"expected directHttpsRequest helper in the validation layer"
);
});

View File

@@ -3,7 +3,7 @@
*
* Task 4 TDD — Fix same-provider combo collision:
* a pool with N connections to the same provider must produce ONE combo
* per model with ALL connection steps + strategy "fill-first".
* per model with ALL connection steps + strategy "quota-share".
*
* Uses "openrouter" (1 model: "auto") as test provider.
*/
@@ -19,9 +19,7 @@ import path from "node:path";
// load. Never delete the SQLite file between tests — under --test-concurrency=4
// modules are cached across files and SQLITE_FILE is frozen at first import.
// Wipe test data via SQL DELETEs instead to avoid cross-file path corruption.
const TEST_DATA_DIR = fs.mkdtempSync(
path.join(os.tmpdir(), "omniroute-quota-combo-balancing-")
);
const TEST_DATA_DIR = fs.mkdtempSync(path.join(os.tmpdir(), "omniroute-quota-combo-balancing-"));
process.env.DATA_DIR = TEST_DATA_DIR;
const core = await import("../../src/lib/db/core.ts");
@@ -29,9 +27,8 @@ const poolsDb = await import("../../src/lib/db/quotaPools.ts");
const providersDb = await import("../../src/lib/db/providers.ts");
const combosDb = await import("../../src/lib/db/combos.ts");
const { syncQuotaCombos } = await import("../../src/lib/quota/quotaCombos.ts");
const { isQuotaModelName, quotaModelName } = await import(
"../../src/lib/quota/quotaModelNaming.ts"
);
const { isQuotaModelName, quotaModelName } =
await import("../../src/lib/quota/quotaModelNaming.ts");
const { PROVIDER_MODELS } = await import("../../open-sse/config/providerModels.ts");
// Trigger migration once at module load so the schema is ready for the first
@@ -98,7 +95,9 @@ test.after(() => {
// Helper
// ---------------------------------------------------------------------------
async function listQuotaCombos(): Promise<Array<{ name: string; models: unknown[]; strategy: unknown }>> {
async function listQuotaCombos(): Promise<
Array<{ name: string; models: unknown[]; strategy: unknown }>
> {
const all = await combosDb.getCombos();
return all
.filter((c) => typeof c.name === "string" && isQuotaModelName(c.name as string))
@@ -116,7 +115,7 @@ const FIRST_MODEL = "auto"; // single model in openrouter registry
// B1 — 2-connection same-provider pool: one combo per model with 2 steps
// ---------------------------------------------------------------------------
test("B1: syncQuotaCombos — 2-connection same-provider pool produces ONE combo per model with 2 steps + fill-first", async () => {
test("B1: syncQuotaCombos — 2-connection same-provider pool produces ONE combo per model with 2 steps + quota-share", async () => {
const modelsForProvider = (PROVIDER_MODELS[PROVIDER] ?? []).map((m) => m.id);
assert.ok(modelsForProvider.length > 0, `${PROVIDER} must have at least one model in registry`);
@@ -152,7 +151,7 @@ test("B1: syncQuotaCombos — 2-connection same-provider pool produces ONE combo
`expected exactly ${modelsForProvider.length} combo(s), one per model`
);
// For each model, assert: one combo, 2 steps, fill-first, both connIds present.
// For each model, assert: one combo, 2 steps, quota-share, both connIds present.
for (const modelId of modelsForProvider) {
// B4: combos are named with the GROUP name ("GroupDemo"), not pool name.
const comboName = quotaModelName("GroupDemo", PROVIDER, modelId);
@@ -167,11 +166,11 @@ test("B1: syncQuotaCombos — 2-connection same-provider pool produces ONE combo
const combo = matchingCombos[0];
// Strategy must be fill-first.
// Strategy must be quota-share.
assert.equal(
combo.strategy,
"fill-first",
`combo "${comboName}" strategy should be "fill-first", got "${combo.strategy}"`
"quota-share",
`combo "${comboName}" strategy should be "quota-share", got "${combo.strategy}"`
);
// Must have exactly 2 steps (one per connection).
@@ -182,9 +181,7 @@ test("B1: syncQuotaCombos — 2-connection same-provider pool produces ONE combo
);
// Both connection IDs must appear in the steps.
const stepConnIds = (combo.models as Array<Record<string, unknown>>).map(
(s) => s.connectionId
);
const stepConnIds = (combo.models as Array<Record<string, unknown>>).map((s) => s.connectionId);
assert.ok(
stepConnIds.includes(idA),
`combo "${comboName}" steps should include connA (${idA}), got: ${JSON.stringify(stepConnIds)}`
@@ -286,7 +283,11 @@ test("B3: syncQuotaCombos — idempotent on 2-connection pool (no duplicates aft
2,
`after 2nd sync, combo "${combo.name}" should still have 2 steps, got ${combo.models.length}`
);
assert.equal(combo.strategy, "fill-first", `combo "${combo.name}" strategy must remain "fill-first"`);
assert.equal(
combo.strategy,
"quota-share",
`combo "${combo.name}" strategy must remain "quota-share"`
);
}
});
@@ -388,7 +389,11 @@ test("B5: after syncQuotaCombos on 2-connection pool, getComboByName returns the
2,
`combo "${comboName}" models.length should be 2, got ${(found.models as unknown[]).length}`
);
assert.equal(found.strategy, "fill-first", `combo "${comboName}" strategy should be "fill-first"`);
assert.equal(
found.strategy,
"quota-share",
`combo "${comboName}" strategy should be "quota-share"`
);
// Verify no second combo by scanning all combos for the same name.
const all = await combosDb.getCombos();

View File

@@ -15,8 +15,8 @@
* (one step pinned to connA). That assertion encoded the OLD COLLISION BUG — a
* second same-provider connection would overwrite the combo, leaving only the last
* connId's step. Task 4 fixes this by grouping all connections into one N-step
* fill-first combo per model. D2.5 and D2.6 now assert the CORRECT behavior:
* models.length === 2 (both connections) and strategy === "fill-first". This is
* quota-share combo per model. D2.5 and D2.6 now assert the CORRECT behavior:
* models.length === 2 (both connections) and strategy === "quota-share". This is
* alignment to the corrected implementation, NOT masking — the prior assertions
* encoded the bug, not the desired behavior.
*
@@ -30,7 +30,7 @@
* D2.4 — enforce: pool with connectionIds [connA, connB]; enforce with connA
* (the primary) still finds the pool — no regression on primary.
* D2.5 — combos: syncQuotaCombos for a 2-connection same-provider pool creates
* one combo per model with 2 steps (both connIds) + strategy fill-first.
* one combo per model with 2 steps (both connIds) + strategy quota-share.
* D2.6 — combos: prune — after removing connB from the pool (→ only connA),
* re-sync collapses each combo to 1 step (connA only).
*/
@@ -55,9 +55,8 @@ const providersDb = await import("../../src/lib/db/providers.ts");
const combosDb = await import("../../src/lib/db/combos.ts");
const { resolveQuotaKeyScope } = await import("../../src/lib/quota/quotaKey.ts");
const { syncQuotaCombos } = await import("../../src/lib/quota/quotaCombos.ts");
const { isQuotaModelName, parseQuotaModelName, quotaModelName } = await import(
"../../src/lib/quota/quotaModelNaming.ts"
);
const { isQuotaModelName, parseQuotaModelName, quotaModelName } =
await import("../../src/lib/quota/quotaModelNaming.ts");
const { PROVIDER_MODELS } = await import("../../open-sse/config/providerModels.ts");
// Trigger migration once at module load so the schema is ready for the first
@@ -124,7 +123,9 @@ test.after(() => {
// Helpers
// ---------------------------------------------------------------------------
async function listQuotaCombos(): Promise<Array<{ name: string; models: unknown[]; strategy: unknown }>> {
async function listQuotaCombos(): Promise<
Array<{ name: string; models: unknown[]; strategy: unknown }>
> {
const all = await combosDb.getCombos();
return all
.filter((c) => typeof c.name === "string" && isQuotaModelName(c.name))
@@ -263,9 +264,7 @@ test("D2.3: enforceQuotaShare — input connectionId matching a non-primary memb
// Assign an API key to the pool.
const API_KEY_ID = "test-key-d23";
poolsDb.upsertAllocations(pool.id, [
{ apiKeyId: API_KEY_ID, weight: 50, policy: "hard" },
]);
poolsDb.upsertAllocations(pool.id, [{ apiKeyId: API_KEY_ID, weight: 50, policy: "hard" }]);
// Confirm allocation exists.
const allocations = listAllocationsForApiKey(API_KEY_ID);
@@ -320,9 +319,7 @@ test("D2.4: enforceQuotaShare — input connectionId matching the PRIMARY member
});
const API_KEY_ID = "test-key-d24";
poolsDb.upsertAllocations(pool.id, [
{ apiKeyId: API_KEY_ID, weight: 50, policy: "hard" },
]);
poolsDb.upsertAllocations(pool.id, [{ apiKeyId: API_KEY_ID, weight: 50, policy: "hard" }]);
// Enforce with connA (the primary).
const resultA = await enforceQuotaShare({
@@ -342,9 +339,9 @@ test("D2.4: enforceQuotaShare — input connectionId matching the PRIMARY member
// D2.5 — combos: syncQuotaCombos for 2-connection same-provider pool
// ---------------------------------------------------------------------------
test("D2.5: syncQuotaCombos — 2-connection same-provider pool creates one combo per model with 2 steps + fill-first (Task 4)", async () => {
test("D2.5: syncQuotaCombos — 2-connection same-provider pool creates one combo per model with 2 steps + quota-share (Task 4)", async () => {
// Task 4: N same-provider connections must produce ONE combo per model with
// ALL connections' steps + strategy "fill-first". The old behavior (single step
// ALL connections' steps + strategy "quota-share". The old behavior (single step
// pinned to connA, strategy "priority") was the collision bug — last upsert won.
const connA = await providersDb.createProviderConnection({
provider: PROVIDER_A,
@@ -384,7 +381,7 @@ test("D2.5: syncQuotaCombos — 2-connection same-provider pool creates one comb
const quotaCombos = await listQuotaCombos();
const comboMap = new Map(quotaCombos.map((c) => [c.name, c]));
// ── Verify PROVIDER_A combos exist with N-step fill-first ─────────────────
// ── Verify PROVIDER_A combos exist with N-step quota-share ─────────────────
for (const modelId of modelsA) {
// Combos are named with the GROUP name ("GroupDemo", from group-demo), not pool name.
const expectedName = quotaModelName("GroupDemo", PROVIDER_A, modelId);
@@ -398,11 +395,11 @@ test("D2.5: syncQuotaCombos — 2-connection same-provider pool creates one comb
`combo ${expectedName} should have 2 steps (both connections), got ${combo.models.length}`
);
// Task 4: strategy must be fill-first.
// Task 4: strategy must be quota-share.
assert.equal(
combo.strategy,
"fill-first",
`combo ${expectedName} strategy should be "fill-first", got "${combo.strategy}"`
"quota-share",
`combo ${expectedName} strategy should be "quota-share", got "${combo.strategy}"`
);
// Both connIds must appear across steps.
@@ -429,7 +426,7 @@ test("D2.5: syncQuotaCombos — 2-connection same-provider pool creates one comb
// ---------------------------------------------------------------------------
test("D2.6: syncQuotaCombos — after removing connB from same-provider pool, re-sync collapses each combo to 1 step (connA only)", async () => {
// Task 4: initially a 2-connection pool produces 2-step fill-first combos.
// Task 4: initially a 2-connection pool produces 2-step quota-share combos.
// After removing connB (pool → only connA), re-sync rebuilds each combo with
// a single step pinned to connA. The combo names are unchanged (same provider/
// model), so no prune happens — the combos are updated in-place.
@@ -498,7 +495,10 @@ test("D2.6: syncQuotaCombos — after removing connB from same-provider pool, re
const afterProviders = new Set(
after.map((c) => parseQuotaModelName(c.name)?.provider).filter(Boolean)
);
assert.ok(afterProviders.has(PROVIDER_A), `${PROVIDER_A} combos should survive after connB removal`);
assert.ok(
afterProviders.has(PROVIDER_A),
`${PROVIDER_A} combos should survive after connB removal`
);
for (const modelId of modelsA) {
const expectedName = quotaModelName("GroupDemo", PROVIDER_A, modelId);
const found = after.find((c) => c.name === expectedName);

View File

@@ -0,0 +1,312 @@
/**
* Unit tests for the dedicated quota-share strategy (Phase 3 #9).
*
* Covers the three mechanisms of the isolated strategy module plus its
* activation wiring:
* 1. per-model bucket gating (accountBuckets.isBucketSaturated)
* 2. DRR (deficit round-robin, quantum proportional to weight)
* 3. P2C over real in-flight counters (quotaShareInflight)
* 4. fail-open behavior (no data / all saturated / empty targets)
* 5. qtSd/ combos are minted with strategy "quota-share"
*
* Runner: node:test + assert/strict (NO vitest, NO jest). Clock is injected via
* the nowMs param on every call — the tested path never reads Date.now().
*/
import { test, describe, beforeEach } from "node:test";
import assert from "node:assert/strict";
import {
selectQuotaShareTarget,
_clearDrrStateForTest,
_getDrrDeficitForTest,
} from "../../open-sse/services/combo/quotaShareStrategy.ts";
import {
incrementInflight,
decrementInflight,
getInflight,
_clearInflightForTest,
DEFAULT_LEASE_MS,
} from "../../open-sse/services/combo/quotaShareInflight.ts";
import {
recordUsage,
_clearBucketsForTest,
} from "../../src/lib/quota/accountBuckets.ts";
import { QUOTA_SHARE_STRATEGY } from "../../src/lib/quota/quotaCombos.ts";
import { INTERNAL_ROUTING_STRATEGY_VALUES } from "../../src/shared/constants/routingStrategies.ts";
import type { ResolvedComboTarget } from "../../open-sse/services/combo/types.ts";
// ---------------------------------------------------------------------------
// Helpers
// ---------------------------------------------------------------------------
const NOW = Date.UTC(2026, 5, 24, 12, 0, 0); // 2026-06-24T12:00:00.000Z
const RESET_AT = new Date(NOW + 3_600_000).toISOString(); // +1h (window still open)
function makeTarget(
executionKey: string,
connectionId: string,
weight = 100,
modelStr = "anthropic/claude-sonnet-4-5"
): ResolvedComboTarget {
return {
kind: "model",
stepId: `step-${executionKey}`,
executionKey,
modelStr,
provider: modelStr.split("/")[0],
providerId: null,
connectionId,
weight,
label: null,
};
}
// ---------------------------------------------------------------------------
// Setup — reset all module state before each case for isolation.
// ---------------------------------------------------------------------------
beforeEach(() => {
_clearBucketsForTest();
_clearDrrStateForTest();
_clearInflightForTest();
});
// ─── quotaShareInflight ─────────────────────────────────────────────────────
describe("quotaShareInflight", () => {
test("increment → getInflight returns 1", () => {
incrementInflight("conn-a", DEFAULT_LEASE_MS, NOW);
assert.equal(getInflight("conn-a", NOW), 1);
});
test("increment twice → getInflight returns 2", () => {
incrementInflight("conn-a", DEFAULT_LEASE_MS, NOW);
incrementInflight("conn-a", DEFAULT_LEASE_MS, NOW);
assert.equal(getInflight("conn-a", NOW), 2);
});
test("decrement after increment → returns 0", () => {
incrementInflight("conn-a", DEFAULT_LEASE_MS, NOW);
decrementInflight("conn-a", NOW);
assert.equal(getInflight("conn-a", NOW), 0);
});
test("decrement below 0 is safe (floors at 0)", () => {
decrementInflight("conn-a", NOW); // no prior increment
assert.equal(getInflight("conn-a", NOW), 0);
});
test("TTL expiry: expired slot returns 0 without an explicit decrement", () => {
const leaseMs = 1_000;
incrementInflight("conn-b", leaseMs, NOW);
assert.equal(getInflight("conn-b", NOW), 1);
assert.equal(getInflight("conn-b", NOW + leaseMs + 1), 0);
});
test("empty connectionId returns 0 (fail-open)", () => {
assert.equal(getInflight("", NOW), 0);
incrementInflight("", DEFAULT_LEASE_MS, NOW); // must not throw / not store
assert.equal(getInflight("", NOW), 0);
});
});
// ─── per-model bucket gating ────────────────────────────────────────────────
describe("gating: per-model bucket saturation", () => {
test("saturated 5h window → that connection is deprioritized, the clean one wins", () => {
recordUsage("conn-sat", "5h", 100, RESET_AT, NOW);
const targets = [makeTarget("ek-sat", "conn-sat"), makeTarget("ek-ok", "conn-ok")];
const result = selectQuotaShareTarget(targets, "combo-5h", "anthropic/claude-sonnet-4-5", NOW);
assert.ok(result.target !== null, "must return a target");
assert.equal(result.target.executionKey, "ek-ok", "non-saturated target must be selected");
// Saturated target stays available as a fallback (deprioritized, not dropped).
assert.ok(
result.orderedTargets.some((t) => t.executionKey === "ek-sat"),
"saturated target must still appear in the fallback list"
);
});
test("saturated 7d window → that connection is deprioritized", () => {
recordUsage("conn-7d", "7d", 100, RESET_AT, NOW);
const targets = [makeTarget("ek-7d", "conn-7d"), makeTarget("ek-clean", "conn-clean")];
const result = selectQuotaShareTarget(targets, "combo-7d", "anthropic/claude-sonnet-4-5", NOW);
assert.equal(result.target?.executionKey, "ek-clean");
});
test("saturated per-model 7d window for the requested model → deprioritized", () => {
recordUsage("conn-pm", "7d:claude-sonnet-4-5", 100, RESET_AT, NOW);
const targets = [
makeTarget("ek-pm", "conn-pm", 100, "anthropic/claude-sonnet-4-5"),
makeTarget("ek-other", "conn-other", 100, "anthropic/claude-sonnet-4-5"),
];
const result = selectQuotaShareTarget(targets, "combo-pm", "anthropic/claude-sonnet-4-5", NOW);
assert.equal(result.target?.executionKey, "ek-other");
});
test("per-model saturation for a DIFFERENT model does NOT deprioritize", () => {
// conn-x is saturated only on 7d:claude-opus-4, but the request is for sonnet.
recordUsage("conn-x", "7d:claude-opus-4", 100, RESET_AT, NOW);
const targets = [makeTarget("ek-x", "conn-x", 100, "anthropic/claude-sonnet-4-5")];
const result = selectQuotaShareTarget(targets, "combo-other-model", "anthropic/claude-sonnet-4-5", NOW);
assert.equal(result.target?.executionKey, "ek-x", "must not be gated by an unrelated model window");
});
test("fail-open: all targets saturated → all eligible again, still returns a target", () => {
recordUsage("conn-1", "5h", 100, RESET_AT, NOW);
recordUsage("conn-2", "5h", 100, RESET_AT, NOW);
const targets = [makeTarget("ek-1", "conn-1"), makeTarget("ek-2", "conn-2")];
const result = selectQuotaShareTarget(targets, "combo-fo", "anthropic/claude-sonnet-4-5", NOW);
assert.ok(result.target !== null, "must not return null when everything is saturated");
assert.equal(result.orderedTargets.length, 2, "both targets remain dispatchable");
});
test("empty targets → returns null (fail-open, no crash)", () => {
const result = selectQuotaShareTarget([], "combo-empty", "anthropic/claude-sonnet-4-5", NOW);
assert.equal(result.target, null);
assert.deepEqual(result.orderedTargets, []);
});
test("no buckets recorded at all → fail-open, first/healthy target selected", () => {
const targets = [makeTarget("ek-a", "conn-a"), makeTarget("ek-b", "conn-b")];
const result = selectQuotaShareTarget(targets, "combo-nodata", "anthropic/claude-sonnet-4-5", NOW);
assert.ok(result.target !== null);
assert.equal(result.orderedTargets.length, 2);
});
});
// ─── DRR ─────────────────────────────────────────────────────────────────────
describe("DRR: deficit round robin", () => {
test("equal weight: two connections alternate across consecutive calls", () => {
const t1 = makeTarget("ek-1", "conn-1", 100);
const t2 = makeTarget("ek-2", "conn-2", 100);
const r1 = selectQuotaShareTarget([t1, t2], "combo-drr", "anthropic/claude-sonnet-4-5", NOW);
const r2 = selectQuotaShareTarget([t1, t2], "combo-drr", "anthropic/claude-sonnet-4-5", NOW);
const selected = [r1.target?.executionKey, r2.target?.executionKey];
assert.ok(selected.includes("ek-1"), "ek-1 must be selected at some point");
assert.ok(selected.includes("ek-2"), "ek-2 must be selected at some point");
});
test("higher weight connection receives proportionally more selections (2:1)", () => {
const t1 = makeTarget("ek-heavy", "conn-heavy", 200); // 2x weight
const t2 = makeTarget("ek-light", "conn-light", 100); // 1x weight
const counts: Record<string, number> = { "ek-heavy": 0, "ek-light": 0 };
for (let i = 0; i < 30; i++) {
const r = selectQuotaShareTarget(
[t1, t2],
"combo-weighted",
"anthropic/claude-sonnet-4-5",
NOW
);
if (r.target) counts[r.target.executionKey]++;
// Simulate the request settling (as a real caller's finally handler would),
// so the P2C in-flight tie-break sees equal load and the DRR weighting shows.
r.decrementInflight();
}
assert.ok(
counts["ek-heavy"] > counts["ek-light"],
`heavy (${counts["ek-heavy"]}) should be selected more than light (${counts["ek-light"]})`
);
// Roughly 2:1 — heavy should be at least ~1.5x light over 30 rounds.
assert.ok(
counts["ek-heavy"] >= counts["ek-light"] * 1.5,
`heavy/light ratio should be ~2:1, got ${counts["ek-heavy"]}:${counts["ek-light"]}`
);
});
test("DRR state is isolated per comboName", () => {
const t = makeTarget("ek-shared", "conn-shared", 100);
selectQuotaShareTarget([t], "combo-A", "anthropic/claude-sonnet-4-5", NOW);
const deficitA = _getDrrDeficitForTest("combo-A", "ek-shared");
const deficitB = _getDrrDeficitForTest("combo-B", "ek-shared");
assert.equal(deficitB, 0, "combo-B deficit must remain 0 (isolated)");
assert.equal(deficitA, 0, "the selected target's deficit must be reset to 0");
});
test("single eligible target is returned unchanged", () => {
const t = makeTarget("ek-solo", "conn-solo", 100);
const result = selectQuotaShareTarget([t], "combo-solo", "anthropic/claude-sonnet-4-5", NOW);
assert.equal(result.target?.executionKey, "ek-solo");
assert.equal(result.orderedTargets.length, 1);
});
});
// ─── P2C in-flight ────────────────────────────────────────────────────────────
describe("P2C in-flight", () => {
test("between two candidates, the one with fewer in-flight wins over the DRR pick", () => {
const t1 = makeTarget("ek-busy", "conn-busy", 100);
const t2 = makeTarget("ek-free", "conn-free", 100);
// Pre-load conn-busy with active in-flight requests.
incrementInflight("conn-busy", DEFAULT_LEASE_MS, NOW);
incrementInflight("conn-busy", DEFAULT_LEASE_MS, NOW);
const result = selectQuotaShareTarget([t1, t2], "combo-p2c", "anthropic/claude-sonnet-4-5", NOW);
assert.equal(
result.target?.executionKey,
"ek-free",
"the target with the lower in-flight load must win the P2C tie-break"
);
});
test("decrementInflight() releases the in-flight load", () => {
const t = makeTarget("ek-dec", "conn-dec", 100);
const result = selectQuotaShareTarget([t], "combo-dec", "anthropic/claude-sonnet-4-5", NOW);
assert.equal(getInflight("conn-dec", NOW), 1, "in-flight should be 1 after a dispatch");
result.decrementInflight();
assert.equal(getInflight("conn-dec", NOW), 0, "in-flight should be 0 after the decrement");
});
test("decrementInflight() is idempotent (safe to call more than once)", () => {
const t = makeTarget("ek-idem", "conn-idem", 100);
const result = selectQuotaShareTarget([t], "combo-idem", "anthropic/claude-sonnet-4-5", NOW);
result.decrementInflight();
result.decrementInflight(); // must not go negative or throw
assert.equal(getInflight("conn-idem", NOW), 0);
});
test("TTL releases in-flight automatically when decrement is never called (abort fallback)", () => {
const t = makeTarget("ek-ttl", "conn-ttl", 100);
const result = selectQuotaShareTarget([t], "combo-ttl", "anthropic/claude-sonnet-4-5", NOW);
// Simulate an aborted request: do NOT call result.decrementInflight().
assert.equal(getInflight("conn-ttl", NOW), 1);
assert.equal(
getInflight("conn-ttl", NOW + DEFAULT_LEASE_MS + 1),
0,
"the slot must auto-expire after the lease, preventing a permanent leak"
);
// The returned callback must remain referenced to satisfy the contract.
assert.equal(typeof result.decrementInflight, "function");
});
});
// ─── activation wiring ──────────────────────────────────────────────────────
describe("activation: qtSd/ combos use strategy 'quota-share'", () => {
test("QUOTA_SHARE_STRATEGY constant equals 'quota-share'", () => {
assert.equal(
QUOTA_SHARE_STRATEGY,
"quota-share",
"quotaCombos must mint qtSd/ combos with the 'quota-share' strategy"
);
});
test("'quota-share' is registered as an INTERNAL routing strategy", () => {
assert.ok(
(INTERNAL_ROUTING_STRATEGY_VALUES as readonly string[]).includes("quota-share"),
"'quota-share' must be in the internal (non-UI) routing strategy list"
);
});
});

View File

@@ -134,8 +134,10 @@ test("parseSSEToOpenAIResponse still returns null for an error-only SSE (boundar
test("PART 1: windsurf authHint references the `Windsurf: Provide Auth Token` command", () => {
const here = path.dirname(fileURLToPath(import.meta.url));
// After the providers.ts oauth-constants split, the windsurf authHint moved to
// src/shared/constants/providers/oauth.ts.
const providers = readFileSync(
path.join(here, "../../src/shared/constants/providers.ts"),
path.join(here, "../../src/shared/constants/providers/oauth.ts"),
"utf8"
);