From 4b3438cc5ca92516c646ece96e02f7ac794f74a6 Mon Sep 17 00:00:00 2001 From: Connor Pearson Date: Fri, 12 Jul 2024 18:35:53 +0200 Subject: [PATCH] fix(cache): remove cached value when revalidation results in an error or invalid value --- src/runtime/internal/cache.ts | 38 ++++++++++++++++++++++++++--------- 1 file changed, 28 insertions(+), 10 deletions(-) diff --git a/src/runtime/internal/cache.ts b/src/runtime/internal/cache.ts index 03f72a1d01..171b985788 100644 --- a/src/runtime/internal/cache.ts +++ b/src/runtime/internal/cache.ts @@ -109,16 +109,22 @@ export function defineCachedFunction( entry.mtime = Date.now(); entry.integrity = integrity; delete pending[key]; - if (validate(entry) !== false) { - const promise = useStorage() - .setItem(cacheKey, entry) - .catch((error) => { - console.error(`[nitro] [cache] Cache write error.`, error); - useNitroApp().captureError(error, { event, tags: ["cache"] }); - }); - if (event?.waitUntil) { - event.waitUntil(promise); - } + const promise = + validate(entry) === false + ? useStorage() + .removeItem(cacheKey) + .catch((error) => { + console.error(`[nitro] [cache] Cache write error.`, error); + useNitroApp().captureError(error, { event, tags: ["cache"] }); + }) + : useStorage() + .setItem(cacheKey, entry) + .catch((error) => { + console.error(`[nitro] [cache] Cache write error.`, error); + useNitroApp().captureError(error, { event, tags: ["cache"] }); + }); + if (event?.waitUntil) { + event.waitUntil(promise); } } }; @@ -135,6 +141,18 @@ export function defineCachedFunction( _resolvePromise.catch((error) => { console.error(`[nitro] [cache] SWR handler error.`, error); useNitroApp().captureError(error, { event, tags: ["cache"] }); + + // SWR revalidation failed, remove existing entry so we do + // not continue to return the cached value indefinitely. + const promise = useStorage() + .removeItem(cacheKey) + .catch((error) => { + console.error(`[nitro] [cache] Cache write error.`, error); + useNitroApp().captureError(error, { event, tags: ["cache"] }); + }); + if (event?.waitUntil) { + event.waitUntil(promise); + } }); return entry; }