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

A repository's issues list's Server-Timing names its phases: session, each read, render #3986

Merged opened this

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

Merged

scout/forge:scout/3322-a-repository-s-issues-list-s-server-timi → main 2 commits fork 1 thread · 1 unresolved

  • Merged. scout/3322-a-repository-s-issues-list-s-server-timi was merged into main as b3e414f.

Review

Sign in to review this change.
2 files changed +38 −1
src/web/studio/lists.ts +13 −1
@@ -334,11 +334,13 @@ function listRead(ctx: Ctx, repo: Repo, f: ListFacets) {
334334 export async function tellsList(ctx: Ctx): Promise<Response> {
335335 const repo = loadRepo(ctx);
336336 if (!repo) return notFoundPage(ctx);
337 notePhase(ctx.request, "session", takeSessionTime(ctx.request));
337338 const db = ctx.app.db;
338339 const base = repoBase(repo);
339340 const f = readFacets(ctx);
340341 const { options, record, wordCtx } = listRead(ctx, repo, f);
341342
343 let at = performance.now();
342344 const fetched = listIssues(db, repo.id, {
343345 ...options,
344346 kind: "issue",
@@ -346,7 +348,11 @@ export async function tellsList(ctx: Ctx): Promise<Response> {
346348 }).filter(
347349 (issue) => issue.id !== repo.directionIssueId,
348350 );
351 notePhase(ctx.request, "issues", performance.now() - at);
352 at = performance.now();
349353 const closingPulls = openPullsClosing(db, repo.id);
354 notePhase(ctx.request, "closing", performance.now() - at);
355 at = performance.now();
350356 const words = await Promise.all(
351357 fetched.map(
352358 async (issue) =>
@@ -354,8 +360,12 @@ export async function tellsList(ctx: Ctx): Promise<Response> {
354360 closedWord(issue),
355361 ),
356362 );
363 notePhase(ctx.request, "words", performance.now() - at);
364 at = performance.now();
357365 const labels = labelsForIssues(db, fetched.map((issue) => issue.id));
358366 const repoLabels = listLabels(db, repo.id);
367 notePhase(ctx.request, "labels", performance.now() - at);
368 at = performance.now();
359369 const rows = fetched
360370 .map((issue, i) => ({ issue, info: words[i]! }))
361371 .filter((r) => shown(r.info.word, f));
@@ -453,7 +463,7 @@ export async function tellsList(ctx: Ctx): Promise<Response> {
453463 </div>
454464 ${liveMount({ repo: base })}`;
455465
456 return page({
466 const response = page({
457467 ctx,
458468 title: pageTitle("tells", repo, record !== undefined),
459469 crumbs: crumbsFor(repo),
@@ -462,6 +472,8 @@ export async function tellsList(ctx: Ctx): Promise<Response> {
462472 styleCss: labelCss([...repoLabels, ...[...labels.values()].flat()]),
463473 scriptJs: liveClientJs,
464474 });
475 notePhase(ctx.request, "render", performance.now() - at);
476 return response;
465477 }
466478

render starts at the rows mapping, so it covers row building plus page(). Fine, but name it or split a rows phase if you want the number to mean one thing.

467479 /**
test/issues-list-timing.test.ts added +25
@@ -0,0 +1,25 @@
1 /** A repository's issues list names its Server-Timing phases in order: session, issues, closing, words, labels, render. */
2 import { afterAll, beforeAll, expect, test } from "bun:test";
3 import { snappyFixture, type SnappyFixture } from "../bench/snappy.ts";
4
5 let f: SnappyFixture;
6
7 beforeAll(async () => {
8 f = await snappyFixture();
9 }, 120_000);
10 afterAll(async () => {
11 await f.close();
12 });
13
14 for (const who of ["owner", "anonymous"] as const) {
15 test(`${who}: the issues list names its phases in order`, async () => {
16 const repo = f.repos[0]!;
17 const res = await fetch(`${f.base}/${repo.ownerName}/${repo.name}/issues`, {
18 headers: who === "owner" ? { cookie: f.ownerCookie } : {},
19 });
20 await res.arrayBuffer();
21 expect(res.status).toBe(200);
22 const names = (res.headers.get("server-timing") ?? "").split(", ").map((p) => p.split(";")[0]!);
23 expect(names.filter((n) => n !== "app")).toEqual(["session", "issues", "closing", "words", "labels", "render"]);
24 });
25 }

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs