From cf6546e6d37eba1f39209ca1f5af04a36cfa883a Mon Sep 17 00:00:00 2001 From: Diego Rodrigues de Sa e Souza <8016841+diegosouzapw@users.noreply.github.com> Date: Sun, 21 Jun 2026 18:27:57 -0300 Subject: [PATCH] perf(quota): skip redundant quota_snapshots from idle connections (#4438) (#4565) Closes #4438. Dedupes quota_snapshots writes for idle connections via pure quotaSnapshotChanged() gate. TDD 5/5. Admin-merged over a pre-existing, unrelated base red (model-lockout-max-cooldown.test.ts 'markAccountUnavailable local 404 ... maxCooldownMs', from #4530 incomplete wiring) proven to fail on release/v3.8.33 HEAD without this change. --- CHANGELOG.md | 1 + src/domain/quotaCache.ts | 33 +++++++++++++++++ .../quota-cache-snapshot-dedup-4438.test.ts | 35 +++++++++++++++++++ 3 files changed, 69 insertions(+) create mode 100644 tests/unit/quota-cache-snapshot-dedup-4438.test.ts diff --git a/CHANGELOG.md b/CHANGELOG.md index 33666e6f36..4abc7a10ed 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,7 @@ _In development — bullets added per PR; finalized at release._ - **fix(auto): enforce the quota cutoff before scoring (opt-in)** — auto-routing now evaluates a hard quota cutoff in `buildAutoCandidates` to drop low-quota candidates before scoring, with a 429 guard when all candidates fall below cutoff. The cutoff is **opt-in** behind `QuotaPreflightSettings.enabled` (default OFF via `QUOTA_PREFLIGHT_CUTOFF_ENABLED`), so default behavior is unchanged. ([#4483](https://github.com/diegosouzapw/OmniRoute/pull/4483) — thanks @megamen32) - **fix(antigravity): reasoning/thinking models no longer 400 with `oneOf at '/' not met`** — the Cloud Code envelope passthrough also leaked the Claude/OpenAI-native thinking fields (`thinking`, `reasoning_effort`, `reasoning`, `enable_thinking`, `thinking_budget`) the unified thinking adapter sets at the body root; Google rejected them with `400 Bad input: oneOf at '/' not met`. The whole thinking family is now stripped before the envelope is built; Gemini's own `generationConfig.thinkingConfig` is unaffected. (port from 9router#1926 — thanks @theseven99 / @diegosouzapw) - **fix(integration): restore the codex and memory pipeline contracts** — realigns the CLI fingerprint + memory-tools contracts so the codex and memory pipelines pass their integration checks again. ([#4474](https://github.com/diegosouzapw/OmniRoute/pull/4474) — thanks @KooshaPari) +- **perf(quota): stop writing redundant `quota_snapshots` rows from idle connections** — the 60s background refresh persisted a snapshot for every window of every connection regardless of change, generating 400K+ rows/day from idle accounts. `setQuotaCache` now skips the write when a window's `remaining_percentage`/`is_exhausted` is unchanged from the last cached observation; the first observation and every real change still persist. ([#4438](https://github.com/diegosouzapw/OmniRoute/issues/4438) — thanks @oyi77) ### 📝 Maintenance diff --git a/src/domain/quotaCache.ts b/src/domain/quotaCache.ts index 61017e5123..4a2a5cc4c7 100644 --- a/src/domain/quotaCache.ts +++ b/src/domain/quotaCache.ts @@ -156,6 +156,34 @@ function earliestResetAt(quotas: Record): string | null { return earliest; } +/** + * #4438 — Decide whether a quota snapshot row is worth persisting. + * + * The background refresh ticks every 60s for ALL connections, so idle accounts + * (whose quota never changes) were generating 400K+ identical snapshot rows/day. + * Returns true only when this window has no prior cached observation, or when its + * `remaining_percentage` / `is_exhausted` differs from the last cached entry — so + * the first observation and every real change persist, but idle no-op refreshes + * stop writing. Pure (no I/O) for trivial unit testing. + */ +export function quotaSnapshotChanged( + prior: + | { quotas?: Record; exhausted?: boolean } + | null + | undefined, + windowKey: string, + remainingPercentage: number, + exhausted: boolean +): boolean { + if (!prior) return true; + const priorWindow = prior.quotas?.[windowKey]; + if (!priorWindow) return true; + return ( + priorWindow.remainingPercentage !== remainingPercentage || + (prior.exhausted ?? false) !== exhausted + ); +} + function normalizeQuotas(rawQuotas: Record): Record { const result: Record = {}; for (const [key, q] of Object.entries(rawQuotas)) { @@ -183,6 +211,9 @@ export function setQuotaCache( ) { const quotas = normalizeQuotas(rawQuotas); const exhausted = isExhausted(quotas); + // #4438 — capture the prior entry BEFORE overwriting the cache so we can skip + // redundant snapshot writes for idle connections whose quota didn't change. + const prior = cache.get(connectionId); const entry: QuotaCacheEntry = { connectionId, provider, @@ -201,6 +232,8 @@ export function setQuotaCache( (quotaInfo.total > 0 ? Math.round(((quotaInfo.total - (quotaInfo.used || 0)) / quotaInfo.total) * 100) : 0); + // #4438 — only persist on the first observation or a real change. + if (!quotaSnapshotChanged(prior, windowKey, remainingPercentage, entry.exhausted)) continue; try { saveQuotaSnapshot({ provider, diff --git a/tests/unit/quota-cache-snapshot-dedup-4438.test.ts b/tests/unit/quota-cache-snapshot-dedup-4438.test.ts new file mode 100644 index 0000000000..000a879d03 --- /dev/null +++ b/tests/unit/quota-cache-snapshot-dedup-4438.test.ts @@ -0,0 +1,35 @@ +import { test } from "node:test"; +import assert from "node:assert/strict"; + +import { quotaSnapshotChanged } from "@/domain/quotaCache"; + +// Regression guard for #4438: quota_snapshots generated 400K+ rows/day because +// setQuotaCache wrote a snapshot row for EVERY window of EVERY connection on each +// 60s background refresh, even for idle connections whose quota never changed. +// quotaSnapshotChanged() gates the write so unchanged idle connections stop +// generating rows, while the first observation and every real change still persist. + +test("#4438 writes when there is no prior cache entry (baseline row)", () => { + assert.equal(quotaSnapshotChanged(null, "daily", 100, false), true); + assert.equal(quotaSnapshotChanged(undefined, "daily", 42, false), true); +}); + +test("#4438 writes when the window was never seen before", () => { + const prior = { quotas: { weekly: { remainingPercentage: 80 } }, exhausted: false }; + assert.equal(quotaSnapshotChanged(prior, "daily", 80, false), true); +}); + +test("#4438 skips when remaining_percentage and is_exhausted are unchanged (idle connection)", () => { + const prior = { quotas: { daily: { remainingPercentage: 73 } }, exhausted: false }; + assert.equal(quotaSnapshotChanged(prior, "daily", 73, false), false); +}); + +test("#4438 writes when remaining_percentage changed", () => { + const prior = { quotas: { daily: { remainingPercentage: 73 } }, exhausted: false }; + assert.equal(quotaSnapshotChanged(prior, "daily", 72, false), true); +}); + +test("#4438 writes when is_exhausted flipped even if percentage matches", () => { + const prior = { quotas: { daily: { remainingPercentage: 0 } }, exhausted: false }; + assert.equal(quotaSnapshotChanged(prior, "daily", 0, true), true); +});