g1t/apps/web/app/lib/immutable.server.ts
| 1 | /** |
| 2 | * Things that never change once they exist, such as a commit and its diff, |
| 3 | * kept in the data centre's cache so only the first visit pays for them. |
| 4 | * |
| 5 | * Call this only after the viewer is known to be allowed to see the thing: |
| 6 | * the cache is shared by everyone who asks for the same key. |
| 7 | */ |
| 8 | const ORIGIN = "https://immutable.g1t.internal/"; |
| 9 | /** A year: what is cached here does not go stale. */ |
| 10 | const MAX_AGE_SECONDS = 365 * 24 * 60 * 60; |
| 11 | |
| 12 | export async function immutable<T>(key: string, load: () => Promise<T | null>): Promise<T | null> { |
| 13 | const url = ORIGIN + encodeURIComponent(key); |
| 14 | let cache: Cache | null = null; |
| 15 | try { |
| 16 | cache = (caches as unknown as { default: Cache }).default; |
| 17 | const hit = await cache.match(url); |
| 18 | if (hit) return (await hit.json()) as T; |
| 19 | } catch { |
| 20 | // No cache (local development): load it every time. |
| 21 | } |
| 22 | const value = await load(); |
| 23 | if (value != null && cache) { |
| 24 | await cache |
| 25 | .put( |
| 26 | url, |
| 27 | new Response(JSON.stringify(value), { |
| 28 | headers: { "content-type": "application/json", "cache-control": `max-age=${MAX_AGE_SECONDS}, immutable` }, |
| 29 | }), |
| 30 | ) |
| 31 | .catch(() => {}); |
| 32 | } |
| 33 | return value; |
| 34 | } |