pushes on tangled sites.wisp.place/zzstoatzz.io/punch
fun tangled
7
fork

Configure Feed

Select the types of activity you want to include in your feed.

build leaderboard per request; drop the KV cache layer

caching the built payload in KV pinned updatedAt to the last cron
build-time, so every fetch between ticks read as '10 minutes ago'.
now that the build is a single D1 JOIN, cost of per-request build
is trivial and updatedAt always reflects the moment of the fetch.

Co-Authored-By: Claude Opus 4 (1M context) <noreply@anthropic.com>

+16 -26
+16 -26
worker/src/index.ts
··· 10 10 // GET /leaderboard.json serves the stashed payload dynamically — bypasses 11 11 // wisp's edge cache so the UI always sees the latest cron's output. 12 12 13 - import type { Env, KnotRow, LeaderboardPayload } from "./types.ts"; 13 + import type { Env, KnotRow } from "./types.ts"; 14 14 import { drainKnot } from "./drain.ts"; 15 15 import { resolveMissing } from "./handles.ts"; 16 16 import { buildLeaderboard } from "./render.ts"; ··· 22 22 connectTimeoutMs: 6_000, 23 23 } as const; 24 24 25 - const BOARD_KEY = "board"; 26 25 const CORS_HEADERS = { 27 26 "access-control-allow-origin": "*", 28 27 "access-control-allow-methods": "GET, OPTIONS", ··· 57 56 }; 58 57 59 58 async function serveBoard(env: Env): Promise<Response> { 60 - const cached = await env.HANDLES.get(BOARD_KEY); 61 - if (cached) { 62 - return new Response(cached, { 63 - headers: { 64 - "content-type": "application/json; charset=utf-8", 65 - "cache-control": "no-cache, no-store, must-revalidate", 66 - ...CORS_HEADERS, 67 - }, 68 - }); 69 - } 70 - const stub: LeaderboardPayload = { 71 - rows: [], 72 - updatedAt: new Date().toISOString(), 73 - knots: [], 74 - totalPushes: 0, 75 - status: "warming up — first cron tick pending", 76 - }; 77 - return Response.json(stub, { headers: CORS_HEADERS }); 59 + // build fresh per request — one D1 JOIN, under 10ms. no stale cache layer 60 + // between cron writes and HTTP reads, so updatedAt always reflects the 61 + // moment the caller asked (not the last cron tick). 62 + const payload = await buildLeaderboard(env, null); 63 + return new Response(JSON.stringify(payload), { 64 + headers: { 65 + "content-type": "application/json; charset=utf-8", 66 + "cache-control": "no-cache, no-store, must-revalidate", 67 + ...CORS_HEADERS, 68 + }, 69 + }); 78 70 } 79 71 80 72 async function runCycle(env: Env): Promise<void> { ··· 124 116 await resolveMissing(env, [...seenDids]); 125 117 } 126 118 127 - // build + cache in KV; fetch handler serves from there 128 - const payload = await buildLeaderboard(env, null); 129 - await env.HANDLES.put(BOARD_KEY, JSON.stringify(payload)); 130 - 119 + // no more caching — render happens on demand at /leaderboard.json. 120 + // update the last_cycle_at meta for observability. 131 121 await env.DB.prepare( 132 122 "UPDATE meta SET value = ? WHERE key = 'last_published_at'", 133 - ).bind(payload.updatedAt).run(); 123 + ).bind(new Date().toISOString()).run(); 134 124 135 - console.log(`cached ${payload.rows.length} rows at ${payload.updatedAt}`); 125 + console.log(`cycle complete; ${seenDids.size} new dids resolved`); 136 126 } 137 127 138 128 async function pickChunk(env: Env, n: number): Promise<KnotRow[]> {