flagon-io/g1t

public

Where people and agents ship software together. The open-source git platform for the whole job: issues, agents, checks and deploys to the edge.

g1t/apps/web/app/lib/cache.server.ts

39 lines1,444 bytesCodeBlame
1import { mustReadFresh } from "./perf.server";
2
3/**
4 * A few seconds of memory for answers that rarely change and are asked on
5 * every page, such as the sidebar's projects and the workspace's spend:
6 * kept per isolate, by a key that names the viewer, so one person's answer
7 * is never another's.
8 *
9 * Never used while the answer must be current: during a request that
10 * writes, and for a while after the person's last write (lib/perf.ts,
11 * `PRIMARY_WINDOW_SECONDS`). Failures and `{ ok: false }` results are not
12 * kept.
13 */
14const kept = new Map<string, { until: number; value: unknown }>();
15
16/** Entries kept at most; the oldest go first. */
17const MAX_ENTRIES = 2_000;
18
19/**
20 * Only settled answers are kept, never a promise still in flight: a
21 * Worker's I/O belongs to the request that started it, so another request
22 * must not wait on it.
23 */
24export async function shortCache<T>(key: string, ttlMs: number, load: () => Promise<T>): Promise<T> {
25 if (mustReadFresh()) {
26 kept.delete(key);
27 return load();
28 }
29 const hit = kept.get(key);
30 if (hit && hit.until > Date.now()) return hit.value as T;
31 const value = await load();
32 const failed = typeof value === "object" && value != null && "ok" in value && value.ok === false;
33 if (!failed) {
34 kept.delete(key);
35 kept.set(key, { until: Date.now() + ttlMs, value });
36 if (kept.size > MAX_ENTRIES) kept.delete(kept.keys().next().value as string);
37 }
38 return value;
39}