From e4166b14fc0eb9cd39b4f81f18a6623a11070bd7 Mon Sep 17 00:00:00 2001 From: Yasser Lahbibi Date: Sat, 10 Dec 2022 10:55:54 +0100 Subject: [PATCH 1/4] feat: add force refresh fn --- src/runtime/cache.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/runtime/cache.ts b/src/runtime/cache.ts index 878ffd48cb..45358e316d 100644 --- a/src/runtime/cache.ts +++ b/src/runtime/cache.ts @@ -21,6 +21,7 @@ export interface CacheOptions { getKey?: (...args: any[]) => string; transform?: (entry: CacheEntry, ...args: any[]) => any; validate?: (entry: CacheEntry) => boolean; + refresh?: () => boolean; group?: string; integrity?: any; maxAge?: number; @@ -69,6 +70,7 @@ export function defineCachedFunction( } const expired = + opts.refresh?.() || entry.integrity !== integrity || (ttl && Date.now() - (entry.mtime || 0) > ttl) || !validate(entry); From da79e5ba468fcfe461357a4128efa7182392aba0 Mon Sep 17 00:00:00 2001 From: Yasser Lahbibi Date: Sat, 10 Dec 2022 11:11:17 +0100 Subject: [PATCH 2/4] fix: add h3event param --- src/runtime/cache.ts | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/runtime/cache.ts b/src/runtime/cache.ts index 45358e316d..12e65094da 100644 --- a/src/runtime/cache.ts +++ b/src/runtime/cache.ts @@ -21,7 +21,7 @@ export interface CacheOptions { getKey?: (...args: any[]) => string; transform?: (entry: CacheEntry, ...args: any[]) => any; validate?: (entry: CacheEntry) => boolean; - refresh?: () => boolean; + refresh?: (...args: any[]) => boolean; group?: string; integrity?: any; maxAge?: number; @@ -54,7 +54,8 @@ export function defineCachedFunction( async function get( key: string, - resolver: () => T | Promise + resolver: () => T | Promise, + refresh?: boolean ): Promise> { // Use extension for key to avoid conflicting with parent namespace (foo/bar and foo/bar/baz) const cacheKey = [opts.base, group, name, key + ".json"] @@ -70,7 +71,7 @@ export function defineCachedFunction( } const expired = - opts.refresh?.() || + refresh || entry.integrity !== integrity || (ttl && Date.now() - (entry.mtime || 0) > ttl) || !validate(entry); @@ -109,7 +110,8 @@ export function defineCachedFunction( return async (...args) => { const key = (opts.getKey || getKey)(...args); - const entry = await get(key, () => fn(...args)); + const refresh = opts.refresh?.(...args); + const entry = await get(key, () => fn(...args), refresh); let value = entry.value; if (opts.transform) { value = (await opts.transform(entry, ...args)) || value; @@ -135,6 +137,7 @@ export interface CachedEventHandlerOptions CacheOptions>, "getKey" | "transform" | "validate" > { + refresh?: (event: H3Event) => boolean; headersOnly?: boolean; } From 14f5de5e973e865e4c0b29f666caa6468c7d3739 Mon Sep 17 00:00:00 2001 From: Yasser Lahbibi Date: Thu, 5 Jan 2023 12:27:21 +0100 Subject: [PATCH 3/4] fix: rename refresh to shouldInvalidateCache --- src/runtime/cache.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/runtime/cache.ts b/src/runtime/cache.ts index f3e9f5b4d5..47653d8aaa 100644 --- a/src/runtime/cache.ts +++ b/src/runtime/cache.ts @@ -21,7 +21,7 @@ export interface CacheOptions { getKey?: (...args: any[]) => string; transform?: (entry: CacheEntry, ...args: any[]) => any; validate?: (entry: CacheEntry) => boolean; - refresh?: (...args: any[]) => boolean; + shouldInvalidateCache?: (...args: any[]) => boolean; group?: string; integrity?: any; maxAge?: number; @@ -55,7 +55,7 @@ export function defineCachedFunction( async function get( key: string, resolver: () => T | Promise, - refresh?: boolean + shouldInvalidateCache?: boolean ): Promise> { // Use extension for key to avoid conflicting with parent namespace (foo/bar and foo/bar/baz) const cacheKey = [opts.base, group, name, key + ".json"] @@ -71,7 +71,7 @@ export function defineCachedFunction( } const expired = - refresh || + shouldInvalidateCache || entry.integrity !== integrity || (ttl && Date.now() - (entry.mtime || 0) > ttl) || !validate(entry); @@ -110,8 +110,8 @@ export function defineCachedFunction( return async (...args) => { const key = (opts.getKey || getKey)(...args); - const refresh = opts.refresh?.(...args); - const entry = await get(key, () => fn(...args), refresh); + const shouldInvalidateCache = opts.shouldInvalidateCache?.(...args); + const entry = await get(key, () => fn(...args), shouldInvalidateCache); let value = entry.value; if (opts.transform) { value = (await opts.transform(entry, ...args)) || value; @@ -134,7 +134,7 @@ export interface ResponseCacheEntry { export interface CachedEventHandlerOptions extends Omit>, "transform" | "validate"> { - refresh?: (event: H3Event) => boolean; + shouldInvalidateCache?: (event: H3Event) => boolean; getKey?: (event: H3Event) => string; headersOnly?: boolean; } From 71e1ec800cc8392ddd16bbc631de10b9b740bf6f Mon Sep 17 00:00:00 2001 From: Yasser Lahbibi Date: Thu, 5 Jan 2023 12:36:41 +0100 Subject: [PATCH 4/4] docs: reference new shouldInvalidateCache option --- .../content/1.guide/1.introduction/5.cache.md | 43 +++++++++++-------- 1 file changed, 25 insertions(+), 18 deletions(-) diff --git a/docs/content/1.guide/1.introduction/5.cache.md b/docs/content/1.guide/1.introduction/5.cache.md index eb75aa541c..42394b6d2e 100644 --- a/docs/content/1.guide/1.introduction/5.cache.md +++ b/docs/content/1.guide/1.introduction/5.cache.md @@ -11,13 +11,13 @@ const cachedFn = cachedEventHandler(fn, options) ### Options -- `name`: Handler name. It will be guessed from function name if not provided and fallback to `_` otherwise. -- `group`: Part of cache name. Useful to organize cache storage. -- `getKey`: A function that accepts same arguments of normal function and should generate cache key. If not provided, a built-in hash function will be used. -- `integrity`: A value that changing it, will invalidate all caches for function. By default will be computed from **function code**. -- `maxAge`: Maximum age that cache is valid in seconds. Default is `1` second. -- `swr`: Enable Stale-While-Revalidate behavior. Enabled by default. - +* `name`: Handler name. It will be guessed from function name if not provided and fallback to `_` otherwise. +* `group`: Part of cache name. Useful to organize cache storage. +* `getKey`: A function that accepts same arguments of normal function and should generate cache key. If not provided, a built-in hash function will be used. +* `integrity`: A value that changing it, will invalidate all caches for function. By default will be computed from **function code**. +* `maxAge`: Maximum age that cache is valid in seconds. Default is `1` second. +* `swr`: Enable Stale-While-Revalidate behavior. Enabled by default. +* `shouldInvalidateCache`: A function that returns a boolean to invalidate the current cache and create a new one. ## Examples @@ -26,9 +26,11 @@ const cachedFn = cachedEventHandler(fn, options) ```js // routes/cached.ts const myFn = cachedEventHandler(async () => { - new Promise(resolve => setTimeout(resolve, 1000)) - return `Response generated at ${new Date().toISOString()}` -}, { swr: true }) + new Promise(resolve => setTimeout(resolve, 1000)) + return `Response generated at ${new Date().toISOString()}` +}, { + swr: true +}) ``` **Example:** Cache a utility function @@ -36,21 +38,26 @@ const myFn = cachedEventHandler(async () => { ```js // utils/index.ts const myFn = cachedFunction(async () => { - new Promise(resolve => setTimeout(resolve, 1000)) - return Math.random() -}, { swr: true }) + new Promise(resolve => setTimeout(resolve, 1000)) + return Math.random() +}, { + swr: true +}) ``` - **Example:** Enable Cache on a group of routes (**🧪 Experimental!**) ```js // nitro.config.ts -import { defineNitroConfig } from 'nitropack' +import { + defineNitroConfig +} from 'nitropack' export default defineNitroConfig({ - routeRules: { - '/blog/**': { swr: true } - } + routeRules: { + '/blog/**': { + swr: true + } + } }) ```