Cache server snapshots for 5 minutes and profiles for an hour

This commit is contained in:
dtonon 2026-08-20 11:20:04 +01:00
parent 9ab145f816
commit 7883e6df8a

View file

@ -8,12 +8,17 @@ import type { Query } from "$lib/forum/query";
// Anonymous relay access for server rendering. The server has no signer, so // 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 // 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 // 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 // relay degrades to an empty page, never a hung request.
// cached briefly to absorb crawler bursts. //
// 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 QUERY_TIMEOUT = 2500;
const PROFILE_TIMEOUT = 1500; const PROFILE_TIMEOUT = 1500;
const CONNECT_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 DEAD_RELAY_TTL = 5 * 60_000;
const CACHE_MAX = 2000; const CACHE_MAX = 2000;
@ -89,11 +94,12 @@ function cachedQuery(
relays: string[], relays: string[],
filter: Filter, filter: Filter,
maxWait: number, maxWait: number,
ttl: number,
): Promise<Event[]> { ): Promise<Event[]> {
const key = relays.join(",") + "|" + JSON.stringify(filter); const key = relays.join(",") + "|" + JSON.stringify(filter);
const now = Date.now(); const now = Date.now();
const hit = cache.get(key); 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(); if (cache.size >= CACHE_MAX) cache.clear();
const result = boundedQuery(relays, filter, maxWait); const result = boundedQuery(relays, filter, maxWait);
cache.set(key, { at: now, result }); cache.set(key, { at: now, result });
@ -101,9 +107,14 @@ function cachedQuery(
} }
export const forumQuery: Query = (filter) => 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 // Profiles mostly live off the forum relay; ask it too for members who only
// published there. // published there.
export const profileQuery: Query = (filter) => export const profileQuery: Query = (filter) =>
cachedQuery([RELAY_URL, ...PROFILE_RELAYS], filter, PROFILE_TIMEOUT); cachedQuery(
[RELAY_URL, ...PROFILE_RELAYS],
filter,
PROFILE_TIMEOUT,
PROFILE_TTL,
);