Created
August 9, 2024 13:40
-
-
Save elmariachi111/bd3ef26a5306cec956fbe225a966fb2e to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
export const DEFAULT_CACHE_SECONDS = 15 | |
/** | |
* We're **not** using upstash or the Vercel KV SDK here to avoid package conflicts | |
* instead we're using vercel KV's REST API directly: https://vercel.com/docs/storage/vercel-kv/rest-api | |
*/ | |
const createClient = <T>({ token, url }: { token: string; url: string }) => { | |
return { | |
get: async (key: string): Promise<T | null> => { | |
const result = await ( | |
await fetch(url, { | |
body: `["GET", "${key}"]`, | |
headers: { | |
Authorization: `Bearer ${token}`, | |
}, | |
method: 'POST', | |
}) | |
).json() | |
if (result.result) { | |
return JSON.parse(result.result) | |
} else { | |
return null | |
} | |
}, | |
set: async ( | |
key: string, | |
value: T, | |
options: { | |
ex?: number | |
}, | |
) => { | |
const result = await ( | |
await fetch( | |
`${url}/set/${key}?EX=${options.ex || DEFAULT_CACHE_SECONDS}`, | |
{ | |
body: JSON.stringify(value), | |
headers: { | |
Authorization: `Bearer ${token}`, | |
}, | |
method: 'POST', | |
}, | |
) | |
).json() | |
return result.result | |
}, | |
} | |
} | |
/** | |
* @param fetcher Function a function that returns the data to be cached | |
* @param cacheKey string the cache key | |
* @param options object | |
* @param options.ex number the number of seconds to cache the data | |
* | |
* @returns Promise<any> the data from the fetcher | |
* todo: could be generically typed | |
*/ | |
export const withKVCache = async <T>( | |
fetcher: () => Promise<T>, | |
cacheKey: string, | |
options: { ex: number } = { ex: DEFAULT_CACHE_SECONDS }, | |
) => { | |
const kvClient = | |
process.env.KV_REST_API_URL && process.env.KV_REST_API_TOKEN | |
? createClient<T>({ | |
token: process.env.KV_REST_API_TOKEN, | |
url: process.env.KV_REST_API_URL, | |
}) | |
: undefined | |
if (!kvClient) { | |
return fetcher() | |
} | |
const cacheResult = await kvClient.get(cacheKey) | |
if (cacheResult) { | |
// eslint-disable-next-line no-console | |
console.debug(`[KV_CACHE:HIT] ${cacheKey}`, cacheResult) | |
return cacheResult | |
} | |
const fetchResult = await fetcher() | |
const kvResult = await kvClient.set(cacheKey, fetchResult, { | |
ex: options.ex, | |
}) | |
// eslint-disable-next-line no-console | |
console.debug( | |
`[KV_CACHE:MISS] ${cacheKey} [ex:${options.ex}], cached: ${kvResult}`, | |
) | |
return fetchResult | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment