From 7883e6df8a9f19f6ef89ab8cbce0910ecc074d35 Mon Sep 17 00:00:00 2001 From: dtonon Date: Thu, 20 Aug 2026 11:20:04 +0100 Subject: [PATCH] Cache server snapshots for 5 minutes and profiles for an hour --- src/lib/ssr/relay.ts | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/src/lib/ssr/relay.ts b/src/lib/ssr/relay.ts index 9f647b1..3cf95f9 100644 --- a/src/lib/ssr/relay.ts +++ b/src/lib/ssr/relay.ts @@ -8,12 +8,17 @@ import type { Query } from "$lib/forum/query"; // Anonymous relay access for server rendering. The server has no signer, so // it only ever sees what the relay serves the public; members get their // private rooms once the client takes over. Every query is bounded so a slow -// relay degrades to an empty page, never a hung request, and results are -// cached briefly to absorb crawler bursts. +// relay degrades to an empty page, never a hung request. +// +// Results are cached in memory. Freshness only matters to crawlers and cold +// refreshes — the browser always refetches live data after hydration — so +// forum data lives as long as the edge cache (CACHE_CONTROL's s-maxage) and +// profiles, which rarely change, for an hour. const QUERY_TIMEOUT = 2500; const PROFILE_TIMEOUT = 1500; const CONNECT_TIMEOUT = 1500; -const CACHE_TTL = 30_000; +const FORUM_TTL = 5 * 60_000; +const PROFILE_TTL = 60 * 60_000; const DEAD_RELAY_TTL = 5 * 60_000; const CACHE_MAX = 2000; @@ -89,11 +94,12 @@ function cachedQuery( relays: string[], filter: Filter, maxWait: number, + ttl: number, ): Promise { const key = relays.join(",") + "|" + JSON.stringify(filter); const now = Date.now(); const hit = cache.get(key); - if (hit && now - hit.at < CACHE_TTL) return hit.result; + if (hit && now - hit.at < ttl) return hit.result; if (cache.size >= CACHE_MAX) cache.clear(); const result = boundedQuery(relays, filter, maxWait); cache.set(key, { at: now, result }); @@ -101,9 +107,14 @@ function cachedQuery( } export const forumQuery: Query = (filter) => - cachedQuery([RELAY_URL], filter, QUERY_TIMEOUT); + cachedQuery([RELAY_URL], filter, QUERY_TIMEOUT, FORUM_TTL); // Profiles mostly live off the forum relay; ask it too for members who only // published there. export const profileQuery: Query = (filter) => - cachedQuery([RELAY_URL, ...PROFILE_RELAYS], filter, PROFILE_TIMEOUT); + cachedQuery( + [RELAY_URL, ...PROFILE_RELAYS], + filter, + PROFILE_TIMEOUT, + PROFILE_TTL, + );