Added response data cache + invalidation + revalidation

This commit is contained in:
DrMint 2024-06-15 20:25:24 +02:00
parent 47668e3b29
commit 4ac350d7f5
3 changed files with 57 additions and 0 deletions

View File

@ -1,6 +1,7 @@
import type { APIRoute } from "astro"; import type { APIRoute } from "astro";
import { Collections, type WebHookMessage } from "src/shared/payload/payload-sdk"; import { Collections, type WebHookMessage } from "src/shared/payload/payload-sdk";
import { import {
invalidateDataCache,
refreshCurrencies, refreshCurrencies,
refreshLocales, refreshLocales,
refreshWebsiteConfig, refreshWebsiteConfig,
@ -17,6 +18,10 @@ export const POST: APIRoute = async ({ request }) => {
const message = (await request.json()) as WebHookMessage; const message = (await request.json()) as WebHookMessage;
console.log("[Webhook] Received message from CMS:", message); console.log("[Webhook] Received message from CMS:", message);
if (message.id) {
await invalidateDataCache(message.id);
}
switch (message.collection) { switch (message.collection) {
case Collections.Wordings: case Collections.Wordings:
await refreshWordings(); await refreshWordings();

View File

@ -2128,5 +2128,6 @@ export const getPayloadSDK = ({
await request(payloadApiUrl(Collections.Videos, `id/${id}`)), await request(payloadApiUrl(Collections.Videos, `id/${id}`)),
getRecorderByID: async (id: string): Promise<EndpointRecorder> => getRecorderByID: async (id: string): Promise<EndpointRecorder> =>
await request(payloadApiUrl(Collections.Recorders, `id/${id}`)), await request(payloadApiUrl(Collections.Recorders, `id/${id}`)),
request: async (url: string): Promise<any> => await request(url),
}; };
}; };

View File

@ -8,6 +8,9 @@ import { getPayloadSDK } from "src/shared/payload/payload-sdk";
let token: string | undefined = undefined; let token: string | undefined = undefined;
let expiration: number | undefined = undefined; let expiration: number | undefined = undefined;
const responseCache = new Map<string, any>();
const idsCacheMap = new Map<string, Set<string>>();
export const payload = getPayloadSDK({ export const payload = getPayloadSDK({
apiURL: import.meta.env.PAYLOAD_API_URL, apiURL: import.meta.env.PAYLOAD_API_URL,
email: import.meta.env.PAYLOAD_USER, email: import.meta.env.PAYLOAD_USER,
@ -30,8 +33,56 @@ export const payload = getPayloadSDK({
console.log("[PayloadSDK] New token set. TTL is", diffInMinutes, "minutes."); console.log("[PayloadSDK] New token set. TTL is", diffInMinutes, "minutes.");
}, },
}, },
responseCache: {
get: (url) => {
const cachedResponse = responseCache.get(url);
if (!cachedResponse) {
console.log("[ResponseCaching] No cached response found for", url);
return undefined;
}
console.log("[ResponseCaching] Retrieved cache response for", url);
return cachedResponse;
},
set: (url, response) => {
const stringData = JSON.stringify(response);
const regex = /[a-f0-9]{24}/g;
const ids = [...stringData.matchAll(regex)].map((match) => match[0]);
const uniqueIds = [...new Set(ids)];
uniqueIds.forEach((id) => {
const current = idsCacheMap.get(id);
if (current) {
current.add(url);
} else {
idsCacheMap.set(id, new Set([url]));
}
});
console.log("[ResponseCaching] Caching response for", url);
responseCache.set(url, response);
},
},
}); });
export const invalidateDataCache = async (id: string) => {
const responsesToInvalidate = idsCacheMap.get(id);
if (!responsesToInvalidate) return;
idsCacheMap.delete(id);
for (const url of responsesToInvalidate) {
responseCache.delete(url);
try {
await payload.request(url);
console.log("[ResponseCaching][Invalidation] Success for", url);
} catch (e) {
console.log("[ResponseCaching][Invalidation] Failure for", url);
}
}
console.log("[ResponseCaching] There are currently", responseCache.size, "responses in cache.");
};
type Cache = { type Cache = {
locales: Language[]; locales: Language[];
currencies: string[]; currencies: string[];