Commit Graph

2 Commits

Author SHA1 Message Date
kshitij c015663b21 fix(models): corrupt-at cache rows degrade to live fetch in cached_provider_model_ids
Surfaced during the post-merge review pass on our own #81113 follow-up:
cached_fetch_api_models gained _cache_entry_valid (numeric-'at'
validation) but its sibling cached_provider_model_ids still did
float(entry.get('at', 0)), which raises ValueError/TypeError on a
hand-edited or corrupted provider_models_cache.json row and propagates
uncaught into the /model picker call sites. Same fix, same helper:
corrupt rows are now a cache miss (live fetch), never an exception.
Both wrappers now share the identical validity predicate, closing the
divergence the 'mirrors' docstring promised away.

Also two test nits from the same review: unused OrderedDict import
dropped and the drain-order assertion strengthened to pin LRU-first
FIFO order in tests/gateway/test_agent_cache_pressure.py.

Mutation-checked: restoring the raising float() form makes the new
corrupt-at tests fail.
2026-08-07 23:00:28 +05:30
Teknium 9772e3b189 perf(model-picker): serve stale model caches instantly, refresh in background
The remaining /model picker stall after the Copilot backoff fix: whenever
the 1h provider-models disk cache TTL (or the remote model-catalog manifest
TTL) lapsed mid-session, the next picker open blocked on 8-9 serial
/v1/models round-trips (~2-3s measured) plus the catalog manifest fetch
before rendering anything.

Model catalogs change on release timescales, not hourly — so both caches
now use stale-while-revalidate:

- cached_provider_model_ids(): an expired entry whose credential
  fingerprint still matches is served immediately; a deduped daemon thread
  re-fetches the live catalog and rewrites the disk cache for the next
  open. Entries older than 7 days still block on a live fetch, credential
  rotation still busts the entry, and force_refresh still bypasses SWR.
- model_catalog.get_catalog(): an expired disk manifest is served
  immediately with an off-thread refresh; only a truly cold cache (no disk
  copy) blocks on the network.

Measured picker payload build with deliberately-expired caches:
2.9s -> 0.93s (first open in process) / 0.06s (subsequent opens).
Combined with the Copilot fix (#76386): 7.3s -> ~0.06s for the common case.
2026-08-01 14:52:18 -07:00