Skip to content
186 linesCodeBlameRaw

Pick any line to see why it is the way it is: the commit, the pull request and issue it came from, and what the agent was thinking.

Fast pages, required checks on the branch, self-hosted runners, honest incidents1import { AsyncLocalStorage } from "node:async_hooks";
2
3import type { ServiceBinding } from "@g1t/contracts";
4
5import {
6 type Bookmarks,
7 type ServiceTiming,
8 PRIMARY_WINDOW_SECONDS,
9 bookmarkCookie,
10 coveredMs,
11 mayWrite,
Public pages cacheable again: a signed-out GET never sets g1t_d1; stars, about and public_links are reads12 setsBookmark,
Fast pages, required checks on the branch, self-hosted runners, honest incidents13 readBookmarks,
14 rpcMethodOf,
15 serverTiming,
16 serviceDuration,
Git storage hardened, pages in tens of milliseconds, honest security alerts, and costs reconciled daily17 databaseTime,
Fast pages, required checks on the branch, self-hosted runners, honest incidents18 sessionFor,
19 SESSION_SERVICES,
20} from "./perf";
Give slow reads and long jobs the time they need to finish21import { deadlineFor, withDeadline } from "./deadline";
Fast pages, required checks on the branch, self-hosted runners, honest incidents22
23/**
24 * What one request to the site did: when it started, each service call
25 * and how long it took, each loader, and the D1 bookmarks it read with and
26 * got back. Kept per request with AsyncLocalStorage, so the service
27 * clients, which are shared by every request in the isolate, can record
28 * into the right one.
29 */
30type RequestPerf = {
31 started: number;
32 /** Not GET or HEAD: an action, a form post. */
33 writing: boolean;
34 /** A service call that may have written (lib/perf.ts `mayWrite`). */
35 wrote: boolean;
36 bookmarks: Bookmarks;
37 returned: Record<string, string>;
38 intervals: [number, number][];
39 services: Record<string, ServiceTiming>;
40 loaders: { id: string; ms: number; kind: "loader" | "action" }[];
41 /** How each session-capable service was asked to read, for the header. */
42 sessions: Map<string, string>;
43};
44
45const scope = new AsyncLocalStorage<RequestPerf>();
46
47/** Runs `handle` with a fresh record for `request`. */
48export function withRequestPerf<T>(request: Request, handle: () => Promise<T>): Promise<T> {
49 const writing = request.method !== "GET" && request.method !== "HEAD";
50 return scope.run(
51 {
52 started: Date.now(),
53 writing,
54 wrote: false,
55 bookmarks: readBookmarks(request.headers.get("cookie")),
56 returned: {},
57 intervals: [],
58 services: {},
59 loaders: [],
60 sessions: new Map(),
61 },
62 handle,
63 );
64}
65
66/**
67 * `binding` with its calls timed, and, for a service that reads D1 with
68 * sessions, the `x-d1-bookmark` each call should carry (lib/perf.ts
69 * `sessionFor`). Only `fetch` is wrapped: the clients use nothing else.
70 */
71export function instrumented(name: string, binding: ServiceBinding): ServiceBinding {
72 return {
73 async fetch(input: string, init?: RequestInit) {
74 const perf = scope.getStore();
Never leave a page stuck on its loading bar75 const method = rpcMethodOf(input);
76 if (!perf) return answerInTime(binding, name, method, input, init);
Fast pages, required checks on the branch, self-hosted runners, honest incidents77 const session = sessionFor(name, perf.bookmarks, perf.writing, Math.floor(Date.now() / 1000));
78 let sent = init;
79 if (session) {
80 const headers = new Headers(init?.headers);
81 headers.set("x-d1-bookmark", session);
82 sent = { ...init, headers };
83 perf.sessions.set(name, session.startsWith("first-") ? session.slice(6) : "bookmark");
84 }
Never leave a page stuck on its loading bar85 if (SESSION_SERVICES.has(name) && mayWrite(method)) perf.wrote = true;
Fast pages, required checks on the branch, self-hosted runners, honest incidents86 const from = Date.now();
Never leave a page stuck on its loading bar87 let response: Response;
88 try {
89 response = await answerInTime(binding, name, method, input, sent);
90 } finally {
91 // A call that failed or ran out of time still took the page's time.
92 perf.intervals.push([from, Date.now()]);
93 }
Fast pages, required checks on the branch, self-hosted runners, honest incidents94 const to = Date.now();
95 const timing = (perf.services[name] ??= { calls: 0, wallMs: 0, serviceMs: 0 });
96 timing.calls += 1;
97 timing.wallMs += to - from;
Git storage hardened, pages in tens of milliseconds, honest security alerts, and costs reconciled daily98 const reported = response.headers.get("server-timing");
99 timing.serviceMs += serviceDuration(reported) ?? 0;
100 const database = databaseTime(reported);
101 if (database) {
102 timing.dbMs = (timing.dbMs ?? 0) + database.ms;
103 timing.dbTrips = (timing.dbTrips ?? 0) + database.trips;
104 }
Fast pages, required checks on the branch, self-hosted runners, honest incidents105 const bookmark = response.headers.get("x-d1-bookmark");
106 if (bookmark && SESSION_SERVICES.has(name)) perf.returned[name] = bookmark;
107 return response;
108 },
109 };
110}
111
112/**
Never leave a page stuck on its loading bar113 * One call to `binding`, answered in full (body read) within its deadline
114 * (lib/deadline.ts): a service that stops answering fails the call rather
115 * than holding the page open. RPC answers are small JSON, so reading the
116 * body here costs nothing and puts it under the deadline too.
117 */
118async function answerInTime(binding: ServiceBinding, name: string, method: string, input: string, init?: RequestInit): Promise<Response> {
Give slow reads and long jobs the time they need to finish119 const ms = deadlineFor(name, method, mayWrite(method));
Never leave a page stuck on its loading bar120 return withDeadline(
121 `${name} ${method || input}`,
122 ms,
123 async (signal) => {
124 const response = await binding.fetch(input, { ...init, signal });
125 const body = await response.arrayBuffer();
126 // A 204 or 304 may not be rebuilt with a body, even an empty one.
127 return new Response(body.byteLength > 0 ? body : null, response);
128 },
129 init?.signal,
130 );
131}
132
133/**
Fast pages, required checks on the branch, self-hosted runners, honest incidents134 * Whether this request must read current data: it writes, or the person
135 * wrote moments ago (lib/perf.ts `PRIMARY_WINDOW_SECONDS`). Caches step
136 * aside then (lib/cache.server.ts).
137 */
138export function mustReadFresh(): boolean {
139 const perf = scope.getStore();
140 if (!perf) return true;
141 if (perf.writing) return true;
142 const at = perf.bookmarks.at;
143 return at != null && Math.floor(Date.now() / 1000) - at < PRIMARY_WINDOW_SECONDS;
144}
145
146/** Records a loader's or action's time, from the route instrumentation. */
147export function recordHandler(id: string, kind: "loader" | "action", ms: number) {
148 scope.getStore()?.loaders.push({ id, kind, ms });
149}
150
151/**
152 * `response` with the request's `Server-Timing`, and, after a request
153 * that may have written, the bookmarks its services returned, so the
154 * person's next pages read at least what they just did.
155 */
156export function finishResponse(request: Request, response: Response): Response {
157 const perf = scope.getStore();
158 if (!perf) return response;
Chat and workspace agents: channels, DMs and named agents you talk to159 // A WebSocket handed over (chat's live socket) goes back as it is: a
160 // copy would lose the socket.
161 if (response.status === 101 || (response as Response & { webSocket?: unknown }).webSocket) return response;
Fast pages, required checks on the branch, self-hosted runners, honest incidents162 // A redirect's headers cannot be changed; a copy's can.
163 const answered = new Response(response.body, response);
164 const sessions = [...perf.sessions].map(([service, how]) => `${service}=${how}`).join(" ");
165 answered.headers.append(
166 "server-timing",
167 serverTiming({
168 totalMs: Date.now() - perf.started,
169 loaders: perf.loaders,
170 rpcMs: coveredMs(perf.intervals),
171 services: perf.services,
172 sessions,
173 }),
174 );
175 // Signing in with GitHub writes on a GET; the session it starts says so.
176 const signedIn = answered.headers.getSetCookie().some((cookie) => cookie.startsWith("g1t_session="));
Public pages cacheable again: a signed-out GET never sets g1t_d1; stars, about and public_links are reads177 const hasSession = /(?:^|;\s*)g1t_session=/.test(request.headers.get("cookie") ?? "");
178 if (setsBookmark({ writing: perf.writing, wrote: perf.wrote, hasSession, signedIn })) {
Fast pages, required checks on the branch, self-hosted runners, honest incidents179 const next: Bookmarks = {
180 at: Math.floor(Date.now() / 1000),
181 services: { ...perf.bookmarks.services, ...perf.returned },
182 };
183 answered.headers.append("set-cookie", bookmarkCookie(next, new URL(request.url).protocol === "https:"));
184 }
185 return answered;
186}