mirror of
https://github.com/dtzp555-max/ocp.git
synced 2026-07-21 21:15:09 +00:00
fix(server): drain F3 fallback queue immediately — invalidate F5 keychain cache before the serialized re-check
Follow-up to the F3/F5/F6 fix (independent-review observation). F5's 30s keychain TTL cache could make F3's post-refresh re-check see the stale (expiring) cached creds for up to ~30s, so a waiter admitted right after the prior real-HOME holder's claude refreshed the keychain would needlessly fall back to real HOME again instead of proceeding ISOLATED. Serialization safety was never at risk (still one real-HOME spawn at a time, no double-refresh); only the drain-to-fast-path optimization lagged. Fix: invalidateKeychainReadCache() clears the F5 TTL cache; resolveSpawnDecision() calls it under the fallback mutex, immediately before the re-check, so the admitted waiter reads FRESH keychain state and drains to the isolated fast path at once. The extra keychain read happens only on the rare real-HOME fallback path and only under the mutex (serialized, one at a time). Alignment: unchanged from the parent commit — proxy-internal keychain/HOME-isolation process logic, no cli.js analogue (cli.js citation DECLARED ABSENT, ALIGNMENT.md Rule 2), no endpoint/header/body, /health shape unchanged, OCP still never performs a refresh_token grant itself (#112). 249 tests pass. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
+12
@@ -471,6 +471,10 @@ async function resolveSpawnDecision() {
|
|||||||
// piling every request into the real HOME.
|
// piling every request into the real HOME.
|
||||||
const release = await realHomeFallbackMutex.acquire();
|
const release = await realHomeFallbackMutex.acquire();
|
||||||
try {
|
try {
|
||||||
|
// Drop the 30s keychain TTL cache so the re-check reads FRESH keychain state — otherwise a
|
||||||
|
// waiter admitted right after the prior holder's claude refreshed the token could still see the
|
||||||
|
// stale (expiring) cached creds and needlessly fall back to real HOME again for up to ~30s.
|
||||||
|
invalidateKeychainReadCache();
|
||||||
const retry = resolveSpawnToken();
|
const retry = resolveSpawnToken();
|
||||||
if (retry) {
|
if (retry) {
|
||||||
release();
|
release();
|
||||||
@@ -1641,6 +1645,14 @@ function readKeychainCreds() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// F3 drain helper: drop the F5 keychain TTL cache so the NEXT getOAuthCredentials() re-reads the
|
||||||
|
// keychain from scratch. Called under the real-HOME fallback mutex just before the re-check, so a
|
||||||
|
// waiter admitted after the prior holder's claude refreshed the keychain sees the FRESH token
|
||||||
|
// immediately (and proceeds ISOLATED) instead of waiting out the ≤30s TTL on the stale creds.
|
||||||
|
function invalidateKeychainReadCache() {
|
||||||
|
_keychainCache.clear();
|
||||||
|
}
|
||||||
|
|
||||||
function getOAuthCredentials() {
|
function getOAuthCredentials() {
|
||||||
// 1. Env var fallback — highest precedence for explicit overrides.
|
// 1. Env var fallback — highest precedence for explicit overrides.
|
||||||
if (process.env.CLAUDE_CODE_OAUTH_TOKEN) {
|
if (process.env.CLAUDE_CODE_OAUTH_TOKEN) {
|
||||||
|
|||||||
Reference in New Issue
Block a user