perf(providers): invalidate cache on oauth credential changes
This commit is contained in:
1 parent
b1867d7bf4
commit
ab4d64f157
3 files changed
+41
-17
No files matched your search
+20
-17
@@ -218,6 +218,23 @@ def _now_iso() -> str:
|
||||
return datetime.now(timezone.utc).isoformat().replace("+00:00", "Z")
|
||||
|
||||
|
||||
def _invalidate_provider_state_caches(provider: str) -> None:
|
||||
"""Invalidate caches derived from provider credential state."""
|
||||
try:
|
||||
from api.config import invalidate_credential_pool_cache
|
||||
|
||||
invalidate_credential_pool_cache(provider)
|
||||
except Exception:
|
||||
logger.debug("Failed to invalidate %s credential cache", provider, exc_info=True)
|
||||
|
||||
try:
|
||||
from api.providers import invalidate_providers_cache
|
||||
|
||||
invalidate_providers_cache()
|
||||
except Exception:
|
||||
logger.debug("Failed to invalidate providers cache after %s credential change", provider, exc_info=True)
|
||||
|
||||
|
||||
def _persist_codex_credentials(hermes_home: Path, token_data: dict[str, Any]) -> Path:
|
||||
"""Persist Codex OAuth credentials to active-profile auth.json."""
|
||||
access_token = str(token_data.get("access_token") or "").strip()
|
||||
@@ -277,12 +294,7 @@ def _persist_codex_credentials(hermes_home: Path, token_data: dict[str, Any]) ->
|
||||
auth["updated_at"] = now
|
||||
path = _write_auth_json(auth, auth_path)
|
||||
|
||||
try:
|
||||
from api.config import invalidate_credential_pool_cache
|
||||
|
||||
invalidate_credential_pool_cache("openai-codex")
|
||||
except Exception:
|
||||
logger.debug("Failed to invalidate openai-codex credential cache", exc_info=True)
|
||||
_invalidate_provider_state_caches("openai-codex")
|
||||
|
||||
return path
|
||||
|
||||
@@ -389,12 +401,7 @@ def _link_anthropic_credentials(hermes_home: Path) -> None:
|
||||
})
|
||||
auth["updated_at"] = now
|
||||
_write_auth_json(auth, auth_path)
|
||||
|
||||
try:
|
||||
from api.config import invalidate_credential_pool_cache
|
||||
invalidate_credential_pool_cache("anthropic")
|
||||
except Exception:
|
||||
logger.debug("Failed to invalidate anthropic credential cache", exc_info=True)
|
||||
_invalidate_provider_state_caches("anthropic")
|
||||
|
||||
|
||||
def _anthropic_public_start_payload(flow_id: str, flow: dict[str, Any]) -> dict[str, Any]:
|
||||
@@ -515,11 +522,7 @@ def _remove_anthropic_link_marker(hermes_home: Path) -> None:
|
||||
pool.pop("anthropic", None)
|
||||
auth["updated_at"] = _now_iso()
|
||||
_write_auth_json(auth, auth_path)
|
||||
try:
|
||||
from api.config import invalidate_credential_pool_cache
|
||||
invalidate_credential_pool_cache("anthropic")
|
||||
except Exception:
|
||||
logger.debug("Failed to invalidate anthropic credential cache", exc_info=True)
|
||||
_invalidate_provider_state_caches("anthropic")
|
||||
|
||||
|
||||
# ── Codex protocol ──────────────────────────────────────────────────────────
|
||||
|
||||
@@ -1025,6 +1025,9 @@ def _get_cached_providers(cache_key: tuple[Any, ...]) -> dict[str, Any] | None:
|
||||
|
||||
def _store_cached_providers(cache_key: tuple[Any, ...], payload: dict[str, Any]) -> dict[str, Any]:
|
||||
with _providers_cache_lock:
|
||||
# Single-entry by design: /api/providers is cacheable only for the
|
||||
# active profile/config snapshot, so clear older snapshots to avoid
|
||||
# retaining unbounded provider metadata across profile switches.
|
||||
_providers_cache.clear()
|
||||
_providers_cache[cache_key] = (time.monotonic(), copy.deepcopy(payload))
|
||||
return payload
|
||||
|
||||
@@ -170,6 +170,24 @@ class TestGetProviders:
|
||||
if hasattr(prov, "invalidate_providers_cache"):
|
||||
prov.invalidate_providers_cache()
|
||||
|
||||
def test_oauth_credential_updates_invalidate_providers_cache(self, monkeypatch, tmp_path):
|
||||
"""OAuth credential updates should invalidate cached Providers responses (#6010)."""
|
||||
from api import oauth
|
||||
from api import providers as prov
|
||||
|
||||
invalidated_credentials = []
|
||||
providers_invalidated = []
|
||||
monkeypatch.setattr(config, "invalidate_credential_pool_cache", invalidated_credentials.append)
|
||||
monkeypatch.setattr(prov, "invalidate_providers_cache", lambda: providers_invalidated.append(True))
|
||||
|
||||
oauth._persist_codex_credentials(
|
||||
tmp_path,
|
||||
{"access_token": "access-token", "refresh_token": "refresh-token"},
|
||||
)
|
||||
|
||||
assert invalidated_credentials == ["openai-codex"]
|
||||
assert providers_invalidated == [True]
|
||||
|
||||
def test_returns_list_of_known_providers(self, monkeypatch, tmp_path):
|
||||
"""GET /api/providers should return a list of all known providers."""
|
||||
_install_fake_hermes_cli(monkeypatch)
|
||||
|
||||
Reference in new issue
Block a user