Repository navigation
fix(quota): resolve Quota Sharing plan from pool's primary connection - #14042
Merged
Merged
Conversation
Multi-connection Quota Sharing pools resolve a DIFFERENT provider plan depending on which member connection actually served a request (write path, enforceQuotaShare/recordConsumption) vs. the pool's primary connection (dashboard read path, /api/quota/pools/[id]/usage). The wizard's "Limite" step PUTs a manual plan override only to the primary connection, so any other pool member fell back to a different (catalog/empty) plan shape. Since the quota_consumption dimension key is poolId:unit:window, a different unit/window meant recordConsumption wrote to a bucket the dashboard never read, so real traffic served via a non-primary connection never appeared as "consumed". Fix: resolve the plan from the pool's canonical primary connection (pool.connectionId) in both enforceQuotaShare and recordConsumption, matching the dashboard's read path. recordConsumption now keeps the matched pool object (not just its id) so it can reach connectionId. getSaturation(input.connectionId, ...) is untouched — that signal is legitimately per-connection.
Collaborator
Author
|
Validated in local merge-train /tmp/mt-train3b.log on 192.168.0.113 @ train tip 408e2128791696a18966681953136fc96aeb99b0 (32 PRs boarded): static gates green; full test:unit 40694 tests, 17 failing — every one reproduces on the pure release tip (base-red sweep list), zero new reds. Merged --admin per merge-gates §4/§7. |
muhamadgalihsaputra
pushed a commit
to niyatna/NiyatnaRoute
that referenced
this pull request
Sep 27, 2026
…rence#13876) (cheaper-inference#14042) Multi-connection Quota Sharing pools resolve a DIFFERENT provider plan depending on which member connection actually served a request (write path, enforceQuotaShare/recordConsumption) vs. the pool's primary connection (dashboard read path, /api/quota/pools/[id]/usage). The wizard's "Limite" step PUTs a manual plan override only to the primary connection, so any other pool member fell back to a different (catalog/empty) plan shape. Since the quota_consumption dimension key is poolId:unit:window, a different unit/window meant recordConsumption wrote to a bucket the dashboard never read, so real traffic served via a non-primary connection never appeared as "consumed". Fix: resolve the plan from the pool's canonical primary connection (pool.connectionId) in both enforceQuotaShare and recordConsumption, matching the dashboard's read path. recordConsumption now keeps the matched pool object (not just its id) so it can reach connectionId. getSaturation(input.connectionId, ...) is untouched — that signal is legitimately per-connection.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Root cause
Multi-connection Quota Sharing pools resolve a DIFFERENT provider plan depending on which member connection actually served a request (write path) vs. the pool's primary connection (dashboard read path). The wizard's "Limite" step PUTs a manual plan override only to the primary connection (
connectionIds[0]); any other pool member falls back to a different (catalog/empty) plan shape. Since thequota_consumptiondimension key ispoolId:unit:window, a different unit/window meansrecordConsumption()writes to a different bucket than the one the dashboard's usage route reads — real traffic never appears as "consumed" even though it genuinely happened.Fix
src/lib/quota/enforce.ts::enforceQuotaShare— resolve the plan frompool.connectionId(the pool's canonical primary connection) instead ofinput.connectionId(the connection that actually served the request).src/lib/quota/enforce.ts::recordConsumption— keep the matchedQuotaPoolobject (not just its id) from the pool-search loop, then resolve the plan frommatchedPool.connectionIdfor the same reason.getSaturation(input.connectionId, ...)is left untouched — that signal is legitimately per-connection.Regression tests
tests/unit/quota-share-multiconn-plan-mismatch.test.ts— RED before the fix (AssertionError: dashboard should show the 5000 tokens actually consumed via conn-secondary, got 0—0 !== 5000), GREEN after.tests/unit/quota-share-multiconn-enforce-cap.test.ts— companion test proving a cap configured on the primary connection's plan is now enforced for a request served by a non-primary pool member (also confirmed RED before / GREEN after during development).Gates run
node scripts/check/check-file-size.mjs— no violation on touched files.node scripts/check/check-complexity.mjs— OK (2857 ≤ 3218 baseline).node scripts/check/check-cognitive-complexity.mjs— OK (1291 ≤ 1437 baseline).npm run typecheck:core— exit 0.npx eslint --suppressions-location config/quality/eslint-suppressions.json <changed files>— clean.node scripts/check/check-changelog-integrity.mjs— OK.quota-sqlite-store,quota-pool-usage-equal-split,quota-pool-usage-summed-budget,quota-enforce-await-store,quota-enforce,quota-equal-split,quota-summed-budget,quota-multiprovider,quota-per-key-model,quota-per-key-model-hotpath,quota-spend-recorder,combo-quota-soft-penalty,quota-epsilon-unconfigured-allow,serial/quota-division-blocks,quota-group-allocations.Closes #13876