feat(response-store): read response metadata from R2 - #3339
Conversation
@vinext/cloudflare
create-vinext-app
@vinext/types
vinext
@cloudflare/workers-response-store
commit: |
|
Performance benchmarksCompared 0 improved · 0 regressed · 6 within ±1.5%
View detailed results and traces 🟢 improvement · 🔴 regression · ⚫ change below 1.5% · paired base/head |
|
/bigbonk review for issues Time limit: 10 minutes. Complete the review and post all findings within that limit. Review exact head 8d28e04. |
|
/bigbonk review for issues Time limit: 10 minutes. Complete the review and post all findings within that limit. Review exact head 41dd24e. |
|
Posted 3 actionable inline findings on head |
|
/bigbonk review for issues Time limit: 10 minutes. Complete the review and post all findings within that limit. Review exact head 41dd24e. |
|
Posted 3 actionable inline findings on head |
|
/bigbonk review for issues Time limit: 10 minutes. Complete the review and post all findings within that limit. Review exact head d86e018. |
|
Posted 4 actionable inline findings on head |
|
/bigbonk review for issues Time limit: 10 minutes. Complete the review and post all findings within that limit. Review exact head 5da0b20. |
|
Posted 1 actionable inline finding on head |
|
/bigbonk review for issues Time limit: 10 minutes. Complete the review and post all findings within that limit. Review exact head 47dd81c. |
|
Posted 1 actionable inline finding on head |
|
/bigbonk review for issues Time limit: 10 minutes. Complete the review and post all findings within that limit. Review exact head 6db8145. |
|
LGTM! |
|
/bigbonk review for issues Time limit: 10 minutes. Complete the review and post all findings within that limit. Review exact head 3d135b5. |
|
Posted 1 actionable inline finding on head |
|
/bigbonk review for issues Time limit: 10 minutes. Complete the review and post all findings within that limit. Review exact head b0f0d57. |
|
/bigbonk review for issues Time limit: 10 minutes. Complete the review and post all findings within that limit. Review exact head d5e05a6. |
|
Posted 2 actionable inline findings on head |
|
/bigbonk review for issues Time limit: 10 minutes. Complete the review and post all findings within that limit. Review exact head b15d3dd. |
|
Posted 1 actionable inline finding on head |
|
/bigbonk review for issues Time limit: 10 minutes. Complete the review and post all findings within that limit. Review exact head 896807a. |
|
LGTM! |
896807a to
53f7c9c
Compare
53f7c9c to
a7a3119
Compare
Summary
activeobjectCompatibility
This is API/deployment compatible, not an in-place warm-cache migration. Existing revision-scoped R2 objects are treated as cold misses and refill through the unchanged API. The new
r2-v1R2 and SQLite layout remains scoped by application Worker version ID while isolating it from legacy cache-Worker rollbacks and rolling deployments. Old objects remain available until version cleanup.Validation
npm run checkinpackages/workers-response-storenpm run build:examplesinpackages/workers-response-storenpx vitest run tests/e2e.test.ts tests/service-binding-e2e.test.ts(65 passed)vp test run tests/cloudflare-response-store-worker.test.ts tests/cache-adapters-config.test.ts(31 passed)git diff --checkR2 operations by scenario
The new layout stores the response body and the metadata needed by the fetch path in one object:
The counts below are normal, uncontended operations per cache key or matched entry. They exclude Workers Cache operations, Durable Object RPC and SQLite operations, user regeneration callbacks, and edge-cache purge API calls.
/activeobject is absent or tombstoned. An absentGetObjectcan appear as R2 error10007in tracing even though the binding resolvesget()tonulland returns a normal Response Store miss.waitUntil()and reuses that ETag.put()for a new keyetagDoesNotMatch: "*".put()replacing an existing keyput()followerput(..., { purgeExisting: true })refresh()purgeEverythingpurge/activewith a zero-byte, higher-revision tombstone.getTagExpiration()For
Nsuccessfully refreshed entries, the normal R2 cost isN HEAD + N PUT. ForNpurged active entries, it is alsoN HEAD + N PUT. Sharding changes the metadata fan-out but not the per-entry R2 count.There are no R2
DELETEoperations in the current runtime path. Purge and failed-publication compensation overwrite the same/activeobject with a higher-revision tombstone. Oversized response headers are stored as a prefix in the same object body and do not add another R2 operation.Conditional-write contention
Durable Object reservations allocate and fence monotonically increasing revisions, but they are not exclusive locks held across R2 I/O. Two reserved revisions, or a write and a purge, can therefore reach the same
/activeobject concurrently. Conditional ETag writes prevent the older revision from overwriting the newer one.The bounded CAS loop has these worst-case operation counts before returning a winner or failing:
These are defensive contention bounds, not normal request costs. A superseded synchronous regeneration can also perform one final GET to load the winning response.