Skip to content

fix(resilience): clear persisted LKGP pin on target exhaustion and skip (#11911) - #12013

Merged
diegosouzapw merged 1 commit into
diegosouzapw:release/v3.8.51from
HouMinXi:fix/11911-lkgp-stale-pin-exhaustion
Aug 29, 2026
Merged

diegosouzapw merged 1 commit into
diegosouzapw:release/v3.8.51from
HouMinXi:fix/11911-lkgp-stale-pin-exhaustion

Conversation

@HouMinXi

Copy link
Copy Markdown
Contributor

Summary

When an auto/* or lkgp combo's target fails and enters exhaustion sets (applyComboTargetExhaustion marks the connection/provider exhausted, e.g. an unauthenticated free-tier connection 401), or when a target is skipped before dispatch due to cooldown, model lockout, or unavailability, the Last Known Good Provider (LKGP) pin was NOT cleared.

This caused the subsequent requests to re-select the same dead provider as their preferred candidate, resulting in repeated failed requests and mass-skipping before falling through.

Fix

  • Centralize LKGP invalidation into clearStaleLKGP(comboName, executionKey, comboId, log, tag) in open-sse/services/combo.ts.
  • Invoke clearStaleLKGP in both handleComboChat and handleRoundRobinCombo when:
    1. applyComboTargetExhaustion marks the provider or connection exhausted.
    2. Targets are skipped before dispatch due to circuit breaker OPEN, provider cooldown, connection cooldown, quota cutoff, or model unavailability.
    3. Body-specific 400 errors terminate the target.
  • Add regression test in tests/unit/lkgp-stale-pin-exhaustion-11911.test.ts verifying that stale pins are cleared on exhaustion and pre-dispatch skips.

Closes #11911

⚠️ base-red inherited: #11874

…ip (diegosouzapw#11911)

- Clear stale LKGP pins when applyComboTargetExhaustion marks a connection/provider exhausted
- Clear stale LKGP pins when targets are skipped before dispatch due to cooldown, lockout, or unavailability
- Prevent subsequent combo requests from repeatedly prioritizing dead providers
- Add regression tests covering handleComboChat and handleRoundRobinCombo LKGP exhaustion clearing

Signed-off-by: Minxi Hou <houminxi@gmail.com>
@HouMinXi
HouMinXi requested a review from diegosouzapw as a code owner August 29, 2026 10:57
@diegosouzapw
diegosouzapw merged commit 38e2baa into diegosouzapw:release/v3.8.51 Aug 29, 2026
13 of 15 checks passed
diegosouzapw pushed a commit that referenced this pull request Aug 30, 2026
…omain off the @/lib/localDb barrel import (#11795 Phase 4) (#12053)

Resynced onto the release tip after #12051/#12052 landed. One real conflict in open-sse/services/combo.ts at both LKGP-clear call sites (handleComboChat + round-robin path): the release tip already has #12013's clearStaleLKGP() helper, which this PR's branch predates — kept the current helper call at both sites, discarding the pre-refactor inline pattern. typecheck:core and the open-sse test suite (vitest, 9/9 on volumeDetector) both green after resync. Thanks for the well-scoped Phase 4 migration.
diegosouzapw pushed a commit that referenced this pull request Aug 30, 2026
#11795 Phase 5) (#12055)

Resynced onto the release tip after #12051/#12052/#12053 landed. Same LKGP-clear conflict as #12053 (kept the current clearStaleLKGP() helper at both call sites). One additional issue this final phase's combined-worktree validation surfaced: clearStaleLKGP() itself (added by #12013, which none of the 4 phase PRs could have seen since it landed after they were authored) still had a dynamic `await import("@/lib/localDb")` — a real break once this PR deletes the barrel. Fixed to `await import("@/lib/db/settings")`, matching the direct-import pattern used at every other call site. typecheck:core, check-db-rules, check:cycles, and the eslint-import-boundaries regression test (3/3, including "G14 rejects localDb barrel imports") all green after resync — zero barrel-importing production files remain. Nice clean 5-phase migration, and thanks for taking on the full #11795 cleanup.
abhisheksharma2411 added a commit to abhisheksharma2411/OmniRoute that referenced this pull request Sep 9, 2026
…ed target

diegosouzapw#12013 cleared the persisted LKGP pin from 13 call sites so a dead provider
stops being re-pinned. None of them look at which provider the pin names, and
the combo-level pin records whichever provider last succeeded — not necessarily
the one failing now.

Under auto the pin is a scoring input rather than a hoist: resolveAutoStrategy
reads it into lastKnownGoodProvider and feeds it to candidate scoring, so the
pinned provider is not necessarily tried first. Skipping an unrelated target —
a connection cooldown, a quota cutoff, an unavailable model — therefore threw
away a preference for a provider that never failed. Under the lkgp strategy the
same call is harmless, because the pinned target is hoisted to the front and so
is always the first thing tried.

Clear the combo-level pin only when it names the failed target's provider, and
— when both carry one — its connection, so a sibling connection failing does
not invalidate the pinned one. The target-scoped executionKey pin is still
cleared unconditionally; it is unambiguously about the target that failed.

Refs diegosouzapw#11911
@HouMinXi
HouMinXi deleted the fix/11911-lkgp-stale-pin-exhaustion branch September 16, 2026 13:47
muhamadgalihsaputra pushed a commit to niyatna/NiyatnaRoute that referenced this pull request Sep 27, 2026
…ip (diegosouzapw#11911) (diegosouzapw#12013)

When an auto/*/lkgp combo target failed into exhaustion (e.g. an unauthenticated free-tier 401) or was skipped pre-dispatch (cooldown, model lockout, unavailability), the Last Known Good Provider pin was never cleared — so subsequent requests kept re-selecting the same dead provider, causing repeated failures and mass-skipping instead of falling through to a healthy target. Centralizes invalidation into clearStaleLKGP(), invoked from both handleComboChat and handleRoundRobinCombo on exhaustion, pre-dispatch skip, and body-specific 400 termination.
muhamadgalihsaputra pushed a commit to niyatna/NiyatnaRoute that referenced this pull request Sep 27, 2026
…omain off the @/lib/localDb barrel import (diegosouzapw#11795 Phase 4) (diegosouzapw#12053)

Resynced onto the release tip after diegosouzapw#12051/diegosouzapw#12052 landed. One real conflict in open-sse/services/combo.ts at both LKGP-clear call sites (handleComboChat + round-robin path): the release tip already has diegosouzapw#12013's clearStaleLKGP() helper, which this PR's branch predates — kept the current helper call at both sites, discarding the pre-refactor inline pattern. typecheck:core and the open-sse test suite (vitest, 9/9 on volumeDetector) both green after resync. Thanks for the well-scoped Phase 4 migration.
muhamadgalihsaputra pushed a commit to niyatna/NiyatnaRoute that referenced this pull request Sep 27, 2026
diegosouzapw#11795 Phase 5) (diegosouzapw#12055)

Resynced onto the release tip after diegosouzapw#12051/diegosouzapw#12052/diegosouzapw#12053 landed. Same LKGP-clear conflict as diegosouzapw#12053 (kept the current clearStaleLKGP() helper at both call sites). One additional issue this final phase's combined-worktree validation surfaced: clearStaleLKGP() itself (added by diegosouzapw#12013, which none of the 4 phase PRs could have seen since it landed after they were authored) still had a dynamic `await import("@/lib/localDb")` — a real break once this PR deletes the barrel. Fixed to `await import("@/lib/db/settings")`, matching the direct-import pattern used at every other call site. typecheck:core, check-db-rules, check:cycles, and the eslint-import-boundaries regression test (3/3, including "G14 rejects localDb barrel imports") all green after resync — zero barrel-importing production files remain. Nice clean 5-phase migration, and thanks for taking on the full diegosouzapw#11795 cleanup.
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.

fix(resilience): Stale LKGP pin survives provider/connection exhaustion — dead free-tier provider re-selected every request

2 participants