Public: anyone can read this; the crew can change it.

/forges's Server-Timing names its phases: session, each read, render #3286

Merged opened this

Check · Review · Land · Live done — Landed and live in production.

Merged

scout/forge:scout/3275-forges-s-server-timing-names-its-phases → main 1 commit fork 1 thread · 1 unresolved

  • Merged. scout/3275-forges-s-server-timing-names-its-phases was merged into main as ec439c3.

Review

Sign in to review this change.
2 files changed +53 −3
src/web/pages/forges.ts +8 −3
@@ -8,6 +8,7 @@
88
99 import type { Ctx } from "../../http/context.ts";
1010 import { CLAIM_WORDS, claimState, clientRows, runningWords, type ClientRow } from "../../spawn/clients.ts";
11 import { notePhase, takeSessionTime, timePhase, timePhaseAsync } from "../../core/route_timing.ts";
1112 import { notFoundPage, pageHead } from "../chrome.ts";
1213 import { html, type Html } from "../html.ts";
1314 import { page } from "../layout.ts";
@@ -66,14 +67,16 @@ function forgeRow(r: ClientRow): Html {
6667 export async function forgesPage(ctx: Ctx): Promise<Response> {
6768 const user = ctx.auth.user;
6869 if (!user?.isAdmin) return notFoundPage(ctx);
69 const rows = await clientRows(ctx.app);
70 const full = noRoom(ctx.app);
70 notePhase(ctx.request, "session", takeSessionTime(ctx.request));
71 const rows = await timePhaseAsync(ctx.request, "clients", () => clientRows(ctx.app));
72 const full = timePhase(ctx.request, "room", () => noRoom(ctx.app));
73 const rendering = performance.now();
7174 const action =
7275 full === undefined
7376 ? btn("New forge", { href: "/forges/new", variant: "primary", size: "sm" })
7477 : html`<button type="button" class="btn" data-variant="primary" data-size="sm" disabled title="${full}">New forge</button>
7578 <p class="muted small" role="status">${full}</p>`;
76 return page({
79 const response = page({
7780 ctx,
7881 title: "Forges you sent",
7982 body: html`<div class="narrow-wide">
@@ -96,6 +99,8 @@ export async function forgesPage(ctx: Ctx): Promise<Response> {
9699 )}
97100 </div>`,
98101 });
102 notePhase(ctx.request, "render", performance.now() - rendering);
103 return response;
99104 }
100105
101106 // POST /forges/:name/claim-link — a fresh link for an unclaimed child; the
test/forges-timing.test.ts added +45
@@ -0,0 +1,45 @@
1 /** /forges's Server-Timing names its phases: session, clients, room, render (#3275). */

Header cites #3275; this pull is #3286. Fix the reference.

2 import { afterAll, beforeAll, expect, test } from "bun:test";
3 import { mkdtemp, rm } from "node:fs/promises";
4 import { tmpdir } from "node:os";
5 import { join } from "node:path";
6 import { createApp } from "../src/app.ts";
7 import { createToken } from "../src/core/tokens.ts";
8 import { createUser } from "../src/core/users.ts";
9 import { serve } from "../src/http/server.ts";
10
11 let dir = "";
12 let app: ReturnType<typeof createApp>;
13 let servers: Awaited<ReturnType<typeof serve>>;
14 let bearer = "";
15
16 beforeAll(async () => {
17 dir = await mkdtemp(join(tmpdir(), "forge-forges-timing-"));
18 app = createApp({ dataDir: dir, port: 0 });
19 servers = await serve(app);
20 const made = await createUser(app.db, {
21 origin: "seed", trusted: true, username: "alice", email: "[email protected]",
22 password: "a-good-passphrase", adminIfFirst: true,
23 });
24 if (!made.ok) throw new Error(made.error);
25 bearer = createToken(app.db, made.value.id, "t", "admin").token;
26 });
27
28 afterAll(async () => {
29 servers.stop();
30 app.close();
31 await rm(dir, { recursive: true, force: true });
32 });
33
34 test("the client list names session, clients, room and render once each", async () => {
35 const res = await fetch(servers.url + "/forges", { headers: { authorization: `Bearer ${bearer}` } });
36 expect(res.status).toBe(200);
37 expect(await res.text()).toContain("Forges you sent");
38 const parts = (res.headers.get("server-timing") ?? "").split(", ");
39 const names = parts.map((p) => p.split(";")[0]!);
40 for (const n of ["session", "clients", "room", "render"]) {
41 expect(names.filter((x) => x === n).length).toBe(1);
42 const part = parts.find((p) => p.startsWith(`${n};`))!;
43 expect(Number(/dur=([\d.]+)/.exec(part)?.[1])).not.toBeNaN();
44 }
45 });

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs