diff --git a/.changeset/green-socks-trade.md b/.changeset/green-socks-trade.md new file mode 100644 index 000000000000..56a625bfceb4 --- /dev/null +++ b/.changeset/green-socks-trade.md @@ -0,0 +1,5 @@ +--- +"@cloudflare/pages-shared": patch +--- + +chore: Remove now-unused asset preservation cache (v1) diff --git a/packages/pages-shared/__tests__/asset-server/handler.test.ts b/packages/pages-shared/__tests__/asset-server/handler.test.ts index 1bf81649f306..b1ba50cb35ea 100644 --- a/packages/pages-shared/__tests__/asset-server/handler.test.ts +++ b/packages/pages-shared/__tests__/asset-server/handler.test.ts @@ -611,90 +611,6 @@ describe("asset-server handler", () => { } `); }); - - test("preservationCacheV1 (fallback)", async () => { - vi.setSystemTime(new Date("2024-05-09")); // 1 day before fallback is disabled - - const deploymentId = "deployment-" + Math.random(); - const metadata = createMetadataObject({ deploymentId }) as Metadata; - const { caches } = createCacheStorage(); - - const preservationCacheV1 = await caches.open("assetPreservationCache"); - - // Write a response to the V1 cache and make sure it persists - await preservationCacheV1.put( - "https://example.com/foo", - new Response("preserved in V1 cache!", { - headers: { - "Cache-Control": "public, max-age=300", - }, - }) - ); - - const preservationRes = await preservationCacheV1.match( - "https://example.com/foo" - ); - - if (!preservationRes) { - throw new Error( - "Did not match preservation cache on https://example.com/foo" - ); - } - - expect(await preservationRes.text()).toMatchInlineSnapshot( - `"preserved in V1 cache!"` - ); - - // Delete the asset from the manifest and ensure it's served from V1 preservation cache - const findAssetEntryForPath = async (_path: string) => { - return null; - }; - const { response, spies } = await getTestResponse({ - request: new Request("https://example.com/foo"), - metadata, - findAssetEntryForPath, - caches, - fetchAsset: () => - Promise.resolve(Object.assign(new Response("hello world!"))), - }); - expect(response.status).toBe(200); - expect(await response.text()).toMatchInlineSnapshot( - `"preserved in V1 cache!"` - ); - expect(Object.fromEntries(response.headers)).toMatchInlineSnapshot(` - { - "access-control-allow-origin": "*", - "cache-control": "public, max-age=300", - "cf-cache-status": "HIT", - "content-type": "text/plain;charset=UTF-8", - "referrer-policy": "strict-origin-when-cross-origin", - "x-content-type-options": "nosniff", - } - `); - // No cache or early hints writes - expect(spies.waitUntil.length).toBe(0); - - // Should disable fallback starting may 10th - vi.setSystemTime(new Date("2024-05-10")); - const { response: response2, spies: spies2 } = await getTestResponse({ - request: new Request("https://example.com/foo"), - metadata, - findAssetEntryForPath, - caches, - fetchAsset: () => - Promise.resolve(Object.assign(new Response("hello world!"))), - }); - expect(response2.status).toBe(404); - expect(Object.fromEntries(response2.headers)).toMatchInlineSnapshot(` - { - "access-control-allow-origin": "*", - "cache-control": "no-store", - "referrer-policy": "strict-origin-when-cross-origin", - } - `); - // No cache or early hints writes - expect(spies2.waitUntil.length).toBe(0); - }); }); describe("isPreservationCacheResponseExpiring()", async () => { diff --git a/packages/pages-shared/asset-server/handler.ts b/packages/pages-shared/asset-server/handler.ts index 603abaa48207..be8b5ae84e32 100644 --- a/packages/pages-shared/asset-server/handler.ts +++ b/packages/pages-shared/asset-server/handler.ts @@ -25,10 +25,8 @@ type BodyEncoding = "manual" | "automatic"; // Before serving a 404, we check the cache to see if we've served this asset recently // and if so, serve it from the cache instead of responding with a 404. // This gives a bit of a grace period between deployments for any clients browsing the old deployment. -export const ASSET_PRESERVATION_CACHE_V1 = "assetPreservationCache"; -// V2 stores the content hash instead of the asset. -// TODO: Remove V1 once we've fully migrated to V2 -export const ASSET_PRESERVATION_CACHE_V2 = "assetPreservationCacheV2"; +// Only the content hash is actually stored in the body. +export const ASSET_PRESERVATION_CACHE = "assetPreservationCacheV2"; const CACHE_CONTROL_PRESERVATION = "public, s-maxage=604800"; // 1 week /** The preservation cache should be periodically @@ -576,14 +574,14 @@ export async function generateHandler< waitUntil( (async () => { try { - const assetPreservationCacheV2 = await caches.open( - ASSET_PRESERVATION_CACHE_V2 + const assetPreservationCache = await caches.open( + ASSET_PRESERVATION_CACHE ); // Check if the asset has changed since last written to cache // or if the cached entry is getting too old and should have // it's expiration reset. - const match = await assetPreservationCacheV2.match(request); + const match = await assetPreservationCache.match(request); if ( !match || assetKey !== (await match.text()) || @@ -599,7 +597,7 @@ export async function generateHandler< ); preservedResponse.headers.set("x-robots-tag", "noindex"); - await assetPreservationCacheV2.put( + await assetPreservationCache.put( request.url, preservedResponse ); @@ -637,30 +635,13 @@ export async function generateHandler< async function notFound(): Promise { if (caches) { try { - const assetPreservationCacheV2 = await caches.open( - ASSET_PRESERVATION_CACHE_V2 + const assetPreservationCache = await caches.open( + ASSET_PRESERVATION_CACHE ); - let preservedResponse = await assetPreservationCacheV2.match( + const preservedResponse = await assetPreservationCache.match( request.url ); - // Continue serving from V1 preservation cache for some time to - // prevent 404s during the migration to V2 - const cutoffDate = new Date("2024-05-17"); - if (!preservedResponse && Date.now() < cutoffDate.getTime()) { - const assetPreservationCacheV1 = await caches.open( - ASSET_PRESERVATION_CACHE_V1 - ); - preservedResponse = await assetPreservationCacheV1.match(request.url); - if (preservedResponse) { - // V1 cache contains full response bodies so we return it directly - if (setMetrics) { - setMetrics({ preservationCacheResult: "checked-hit" }); - } - return preservedResponse; - } - } - // V2 cache only contains the asset key, rather than the asset body: if (preservedResponse) { if (setMetrics) { @@ -674,6 +655,7 @@ export async function generateHandler< } if (assetKey) { const asset = await fetchAsset(assetKey); + if (asset) { // We know the asset hasn't changed, so use the cached headers. return new Response(asset.body, preservedResponse);