Public: anyone can read this; the crew can change it.
A limb's re-plan preview names its Server-Timing phases: session, repo, plan, render #3742
Check · Review · Land · Live done — Landed and live in production.
scout/forge:scout/3740-a-limb-s-re-plan-preview-names-its-serve → main 1 commit fork 1 thread · 1 unresolved
2 files
changed +11
−2
src/web/pages/limb_replan.ts +8 −2
| @@ -11,6 +11,7 @@ import { | ||
| 11 | 11 | type ReplanAction, |
| 12 | 12 | } from "../../actions/limb_replan.ts"; |
| 13 | 13 | import type { Repo } from "../../core/repos.ts"; |
| 14 | import { notePhase, timePhase } from "../../core/route_timing.ts"; | |
| 14 | 15 | import type { Ctx } from "../../http/context.ts"; |
| 15 | 16 | import { |
| 16 | 17 | crumbsFor, |
| @@ -28,12 +29,15 @@ import { milestoneHref } from "./milestones.ts"; | ||
| 28 | 29 | |
| 29 | 30 | /** GET /:owner/:name/milestones/:number/limb?action=replan — what the planner will be given. */ |
| 30 | 31 | export function replanPreviewPage(ctx: Ctx, repo: Repo, number: number): Response { |
| 31 | const plan = previewReplan(ctx.app, ctx.auth.user, repo, number); | |
| 32 | const plan = timePhase(ctx.request, "plan", () => | |
| 33 | previewReplan(ctx.app, ctx.auth.user, repo, number), | |
| 34 | ); | |
| 32 | 35 | if (!plan.ok) return notFoundPage(ctx); |
| 36 | const rendering = performance.now(); | |
| 33 | 37 | const base = repoBase(repo); |
| 34 | 38 | const p = plan.value; |
| 35 | 39 | const back = milestoneHref(base, number); |
| 36 | return page({ | |
| 40 | const response = page({ | |
| 37 | 41 | ctx, |
| 38 | 42 | title: `Re-plan ${p.limb.title} · ${repo.name}`, |
| 39 | 43 | crumbs: crumbsFor(repo), |
| @@ -69,6 +73,8 @@ export function replanPreviewPage(ctx: Ctx, repo: Repo, number: number): Respons | ||
| 69 | 73 | ${btn("Back", { href: back, variant: "ghost" })} |
| 70 | 74 | </form>`}`, |
| 71 | 75 | }); |
| 76 | notePhase(ctx.request, "render", performance.now() - rendering); | |
| 77 | return response; | |
| 72 | 78 | } |
| 73 | 79 | |
| 74 | 80 | /** POST /:owner/:name/milestones/:number/limb with action replan or takeback, its form already read. */ |
test/limb-timing.test.ts +3
| @@ -70,4 +70,7 @@ test("GET /:owner/:name/milestones/:number/limb names its phases", async () => { | ||
| 70 | 70 | expect(defer.find((p) => p.startsWith("pillars;"))).toBeUndefined(); |
| 71 | 71 | const resume = await phases("resume"); |
| 72 | 72 | expect(resume.find((p) => p.startsWith("pillars;"))).toMatch(/^pillars;dur=\d+\.\d$/); |
| 73 | const replan = await phases("replan"); | |
| 74 | for (const name of ["session", "repo", "plan", "render"]) | |
| 75 | expect(replan.find((p) => p.startsWith(`${name};`))).toMatch(/^[a-z]+;dur=\d+\.\d$/); | |
| 73 | 76 | }); |
new above
offline
Render starts here and ends after page() returns, same as limbPreviewPage. Fine. If the page ever streams, this will under-count; note it then.