Repository navigation
fix(core): revalidate the models.dev catalog with its ETag - #58813
Conversation
There was a problem hiding this comment.
Looks good. I ran it against the live models.opencode.ai. On the base, both the forced and the stale refresh downloaded the full catalog and the entry stayed stale. With this change, the stale refresh sent the stored ETag, got a 304 (which the retry layer doesn't retry), and the entry's updatedAt was updated. test/models.test.ts passes, and typecheck:tsc is clean (the typecheck script's bun check isn't available in this Bun).
Public API: unchanged. The ETag is an optional field inside the internal KV cache entry, and older builds ignore it when reading.
No blocking concerns.
1441d31 to
470f08a
Compare
There was a problem hiding this comment.
The new commit looks good. I re-ran it against the live models.opencode.ai. The forced refresh stored the ETag in the meta entry. A stale refresh then got a 304, the meta entry's updatedAt was refreshed, and the catalog entry was left untouched. test/models.test.ts passes, and typecheck:tsc is clean.
Public API: unchanged. The extra :meta KV key is internal, and older builds still read the catalog entry as before.
No new concerns.
Problem
The models.dev refresh runs every 5 minutes. Each tick reads and parses the ~6 MB cached catalog from KV just to check its age, then downloads the whole catalog (about 6 MB raw, ~413 KB brotli) and hashes it, even though models.opencode.ai serves an ETag and answers revalidation with an empty
304. When the body matched the cache it returned early without recording the check, so the next process or tick never saw it as fresh.Change
I moved the freshness info (
updatedAt,digest,etag) into its own small KV key next to the catalog, and the refresh tick only reads that key.get()and older builds read it as before. It's only written when the catalog actually changes.updatedAt/digestfrom the catalog entry once.If-None-Match, and responses without an ETag behave like before.No migration and no public schema change.
Out of scope
Durable Object deployments still can't cache the catalog at all (it's over their 2 MB value limit), so they keep fetching the full body.