Skip to content

feat(resilience): add hierarchical concurrency admission - #11493

Merged
diegosouzapw merged 3 commits into
release/v3.8.51from
merge/7778-hierarchical-admission
Aug 25, 2026
Merged

diegosouzapw merged 3 commits into
release/v3.8.51from
merge/7778-hierarchical-admission

Conversation

@diegosouzapw

Copy link
Copy Markdown
Collaborator

Summary

Cherry-picked from #11323 (by @RaviTharuma) — carries only the 3 commits that
implement the actual feature. That PR's branch had drifted 98 commits behind
release/v3.8.51 and picked up 17 already-merged commits as baggage during a
stale rebase, making its diff (7347 additions across ~90 files, including
unrelated i18n/TTS/compression work) unreviewable as a unit and its mergeable
state CONFLICTING.

Commits carried, author preserved:

  • feat(resilience): add hierarchical concurrency admission — atomically
    acquires cumulative global/provider/account concurrency gates before the
    existing scoped Bottleneck limiter; FIFO acquireMany() with no partial
    reservations, composite idempotent release, queue/abort/timeout/full
    handling; off-by-default whole-process cap
    (requestQueue.globalConcurrentRequests) and per-provider caps
    (providerQuotaOverrides.<provider>.providerConcurrency); wired through
    settings defaults/normalization/PATCH validation/API/dashboard UI.
  • fix(i18n): keep Vietnamese resilience keys aligned
  • fix(i18n): align Brazilian Portuguese resilience keys

Closes #7778

Validation (this branch, isolated combined worktree off release/v3.8.51 tip)

  • npm run typecheck:core — pass
  • node scripts/check/check-file-size.mjs — OK
  • node scripts/check/check-changelog-integrity.mjs — OK, no base bullets lost
  • node scripts/check/check-complexity.mjs — OK (baseline maintained)
  • node scripts/check/check-cognitive-complexity.mjs — OK (baseline maintained)
  • npm run lint — clean when isolated from an unrelated ESLint-10 suppressions
    regression carried by a separate PR in the same merge batch
  • Focused tests, isolated re-run (flake-free ×3):
    • tests/unit/accountSemaphore.test.ts — 11/11 pass
    • tests/unit/chatcore-hierarchical-admission.test.ts — 2/2 pass
    • tests/unit/resilience-settings-provider-quota-overrides.test.ts — 12/12 pass
    • tests/unit/i18n-vi-completeness.test.ts — 5/5 pass

Thanks @RaviTharuma for the design and implementation — this PR exists only to
land it cleanly without the unrelated rebase baggage.

diegosouzapw pushed a commit that referenced this pull request Aug 25, 2026
Validated in a combined-batch worktree off release/v3.8.51 tip alongside #11259 and the cherry-picked #11323 successor (#11493):
- Focused test: tests/unit/oauth-connection-tokenexpiresat-5326.test.ts — 3/3 pass, exercises the round-trip through createProviderConnection/getProviderConnections
- typecheck:core, file-size, changelog-integrity, complexity, cognitive-complexity gates — all OK
- One-string allowlist fix, TDD-proven (fails on base with tokenExpiresAt: null, passes with the change), mutation-checked

Thanks for restoring #5326's fix end to end — clean, minimal, well-tested.
@diegosouzapw
diegosouzapw merged commit a179ffe into release/v3.8.51 Aug 25, 2026
11 of 12 checks passed
@diegosouzapw
diegosouzapw deleted the merge/7778-hierarchical-admission branch August 25, 2026 10:22
jinnnyang pushed a commit to jinnnyang/OmniRoute that referenced this pull request Sep 6, 2026
Two dashboard cards on /dashboard/settings/resilience could not be saved at
all -- every attempt answered `400 Invalid request` regardless of the values
entered. The cause was not operator input but a read/write contract drift:
each card seeds its draft from GET /api/resilience and PATCHes that draft back
verbatim, while the PATCH Zod schemas had fallen behind the settings shape GET
serves.

1. requestQueue -- cheaper-inference#11493 added `globalConcurrentRequests` to
   RequestQueueSettings, normalizeRequestQueueSettings, the defaults and the UI,
   but registered it only on `legacyResilienceDefaultsSchema`, not on
   `requestQueueSettingsSchema`. That object is `.strict()`, so the field GET had
   just emitted came straight back as
   `Unrecognized key: "globalConcurrentRequests"`.
2. comboCooldownWait -- cheaper-inference#8213 (cheaper-inference#7360 follow-up) raised the normalizer ceiling to
   5min and set the default `maxWaitMs` to 90000, while
   `comboCooldownWaitSettingsSchema` kept `.max(30000)`. The block therefore
   failed on its own default value with
   `Too big: expected number to be <=30000`.

Both schemas now mirror their normalizers (0-100000 and 0-300000). The `.strict()`
guarantees are unchanged: unknown keys, non-integers, negatives and
over-ceiling values are still rejected, which the new suite asserts explicitly.

Also surface `error.details[].field` in the ResilienceTab save handler. The API
had been naming the offending field all along; rendering only `error.message`
reduced every validation failure to an undiagnosable "Invalid request" toast,
which is why two independent schema regressions survived a full release cycle.
`formatSaveError` is exported and unit-tested (7 cases).

Regression coverage: tests/unit/resilience-get-patch-shape-parity.test.ts asserts
parameterically that `updateResilienceSchema` accepts every section of the GET
payload as `resolveResilienceSettings()` produces it -- per section and as one
combined body. The pre-existing resilience-tab-response-fields.test.ts only
checked that section NAMES survive the round-trip, never that their CONTENTS
re-validate, which is precisely how both bugs shipped. Any future field added to
a resolved section, or any normalizer bound widened past its schema, now fails
here instead of in production.

Verification (node v24.15.0):
- new suite 13/13 pass; reverting only the schema hunk fails 6 of them
  (both offending sections, the combined body, the tuned-values case and the two
  by-name pins) while the bounds-still-enforced case keeps passing
- tests/unit/resilience-*.test.ts: 126/127 pass. The single failure
  ("alias join: connection provider=cx matches breaker name=codex") reproduces
  identically with these changes stashed -- it is pre-existing on this branch,
  introduced by 6b7b36d (provider alias removal), and untouched here
- typecheck:core: 456 errors before and after, none in the changed files
  (zero net new)
- eslint (3 changed files): clean; prettier --check: clean
- check:changelog-integrity: OK
connorblack added a commit to connorblack/OmniRoute that referenced this pull request Sep 12, 2026
…est queue

GET /api/resilience returns requestQueue.globalConcurrentRequests (added
with hierarchical concurrency admission, cheaper-inference#11493), and the Resilience page
sends the section back unchanged. requestQueueSettingsSchema is strict and
never gained the key, so every save from the page failed with 400
"Unrecognized key: globalConcurrentRequests". The field now takes the same
bounds as legacyResilienceDefaultsSchema: an integer from 0 to 100000.

Also syncs config/site-config.json with the request queue set on the
Service today: requestsPerMinute 35 and concurrentRequests 5.

Claude-Session: https://claude.ai/code/session_01R5zXR8ogxoKtKdxTTJTVBv
muhamadgalihsaputra pushed a commit to niyatna/NiyatnaRoute that referenced this pull request Sep 27, 2026
…ference#11368)

Validated in a combined-batch worktree off release/v3.8.51 tip alongside cheaper-inference#11259 and the cherry-picked cheaper-inference#11323 successor (cheaper-inference#11493):
- Focused test: tests/unit/oauth-connection-tokenexpiresat-5326.test.ts — 3/3 pass, exercises the round-trip through createProviderConnection/getProviderConnections
- typecheck:core, file-size, changelog-integrity, complexity, cognitive-complexity gates — all OK
- One-string allowlist fix, TDD-proven (fails on base with tokenExpiresAt: null, passes with the change), mutation-checked

Thanks for restoring cheaper-inference#5326's fix end to end — clean, minimal, well-tested.
muhamadgalihsaputra pushed a commit to niyatna/NiyatnaRoute that referenced this pull request Sep 27, 2026
…erence#11493)

Cherry-pick of the 3 value commits from cheaper-inference#11323 (by @RaviTharuma), dropping 17 already-merged rebase-baggage commits. Validated in a combined-batch worktree off release/v3.8.51 tip:
- typecheck:core, file-size, changelog-integrity, complexity, cognitive-complexity gates — all OK
- Focused tests, isolated re-run flake-free: accountSemaphore.test.ts 11/11, chatcore-hierarchical-admission.test.ts 2/2, resilience-settings-provider-quota-overrides.test.ts 12/12, i18n-vi-completeness.test.ts 5/5
- lint clean once isolated from the unrelated ESLint-10 suppressions regression carried by a separate PR in the batch

Closes cheaper-inference#7778. Full credit to @RaviTharuma for the design and implementation.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(resilience): hierarchical concurrency limits and queues at global, provider, and account levels

2 participants