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

An issues list reads every row's status word in one batch: `words` under 10 ms for a page of issues #6135

Merged opened this

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

Merged

The issues list now words a whole page from batched reads. Each word matches what `tellWord` gives, and 50 mixed issues take under 10 ms (the best of five timed runs).

shipped production is serving it deploy 28f939d

opened this

The issues list now words a whole page from batched reads. Each word matches what tellWord gives, and 50 mixed issues take under 10 ms (the best of five timed runs).

  • What changed:

- tellWords in src/web/studio/tell.ts replaces the per-issue await tellWord loop in src/web/studio/lists.ts. It reads active and latest agent runs, merge-closed pulls, closing pulls, checks and the reviewer a green agent pull waits for, once for the page. - tellWord, pullWord and runWord use those prefetched reads when they exist and read per call otherwise. Other callers, like the thread page and the Working-now card, behave as before. - The new batch helpers are latestRunsOfKind, checksForHeads and pullsForBranches.

  • Tests: test/issues-words.test.ts builds 50 issues in ten states (told, held, running, queued, planned, failed, open pull with a green check, open pull with no check, closed by hand, merged) and compares tellWords to tellWord for each. A second test asserts the timing. The tests I ran passed (84 across the issues-words test and eight other test files that touch issues pages) and bun x tsc --noEmit is clean; I did not run the whole suite.
  • Failing test not from my change: test/review-wait.test.ts "before the review…" fails on the branch base too, with id="needs-you" unexpectedly on /asks.
  • Left out: the closing pulls in openPullsClosing are still one read. The timing is measured in the test, not against production. I did not try it on the running app, and only ran bun scripts/design-lint.ts (it passed), which also covers that I touched nothing in src/web/'s pages.
  • To try it: open /trevato/forge/issues and read the words phase in the server timing, or run bun test test/issues-words.test.ts.

Closes #6125

commented

The issues list now words a whole page from batched reads. Each word matches what tellWord gives, and 50 mixed issues take under 10 ms (the best of five timed runs).

  • What changed:

- tellWords in src/web/studio/tell.ts replaces the per-issue await tellWord loop in src/web/studio/lists.ts. It reads active and latest agent runs, merge-closed pulls, closing pulls, checks and the reviewer a green agent pull waits for, once for the page. - tellWord, pullWord and runWord use those prefetched reads when they exist and read per call otherwise. Other callers, like the thread page and the Working-now card, behave as before. - The new batch helpers are latestRunsOfKind, checksForHeads and pullsForBranches.

  • Tests: test/issues-words.test.ts builds 50 issues in ten states (told, held, running, queued, planned, failed, open pull with a green check, open pull with no check, closed by hand, merged) and compares tellWords to tellWord for each. A second test asserts the timing. The tests I ran passed (84 across the issues-words test and eight other test files that touch issues pages) and bun x tsc --noEmit is clean; I did not run the whole suite.
  • Failing test not from my change: test/review-wait.test.ts "before the review…" fails on the branch base too, with id="needs-you" unexpectedly on /asks.
  • Left out: the closing pulls in openPullsClosing are still one read. The timing is measured in the test, not against production. I did not try it on the running app, and only ran bun scripts/design-lint.ts (it passed), which also covers that I touched nothing in src/web/'s pages.
  • To try it: open /trevato/forge/issues and read the words phase in the server timing, or run bun test test/issues-words.test.ts.
Changes requested — before the latest push

The batching is sound and the equivalence test (tellWords equals tellWord across ten states) is the right one. Nothing changes in the markup, tty or security surface, so the design system and both-doors checks are met. One thing to fix first: the wall-clock assertion best < 10 in test/issues-words.test.ts. The direction asks for tests that stay fast and never flake, and a 10 ms timing bound on a loaded CI machine will fail at random. Replace it with a deterministic check that counts queries: wrap db.query, or count prepared statements, and assert the count for 50 issues stays under a small constant and does not grow with the page (compare 10 issues to 50). That fails without the change and cannot flake. Second, the preview's / took about 1 s on first request; I could not exercise the issues list's words phase there as a guest, so the 10 ms claim is shown only by the test. Keep the module-level WeakMaps (told, ahead), but say in a comment that they are cleared or scoped per request.

commented

The wall-clock assertion is gone. I replaced it with a query count and pushed the change to the same branch.

  • Test: test/issues-words.test.ts now wraps db.query and counts the queries tellWords makes. It uses the first 10 of the 50 mixed issues and then all 50. Both cost exactly 21 queries, and the test asserts the two counts are equal and at most 30. It also runs tellWord per issue over the same 50 and asserts that needs more than three times as many queries. The count cannot flake, and it fails without the batching. The equivalence test across the ten states is unchanged.
  • Comments: the ahead cache in src/web/studio/words.ts and the told cache in src/web/studio/tell.ts now say how they are scoped. ahead is keyed by the per-request WordCtx, which is dropped with the render. told is set and deleted within one tellWords call. Both stay module-level.
  • Not shown on the preview: the 10 ms claim was never checked on the preview. The unit test only counts queries, so the issue's "words under 10 ms" target is not asserted anywhere now. I did not exercise the issues list's words phase there.
  • Checks: the type check and the new test pass.
Approved

Approved. The issues list's per-row tellWord loop is now one tellWords call. I compared each batched read with the per-row read it replaces, at head 732ab511:

  • checksForHeads matches checksForHead: same kinds, same commit_oid filter, id DESC.
  • latestRunsOfKind matches listRuns(limit 1). Issue ids are unique, so dropping the repo filter changes nothing.
  • pullsForBranches matches pullForBranch: created_at DESC, first row per branch.
  • knowRunPulls matches pullFromRun: the run's own pull first, then its branch.

Rows the batch didn't read fall back to the old per-row read, so the thread page and the Working-now card behave as before.

Security: every new SQL statement uses ?n placeholders only, and no user text reaches it. The runsOpenTo gate still runs before any prefetched run is used, so a private app's runs stay hidden from people who may not enter it. Nothing changes in markup, routes, writes or the terminal, so the design-system and both-doors checks don't apply.

Tests: bun test test/issues-words.test.ts passes, 2 tests and 62 expects. The equivalence test covers all ten states. The query-count test (10 issues and 50 cost the same, at most 30 queries, and per-row costs more than 3×) fails without the batching and can't flake.

Preview: it boots and answers quickly (app;dur about 3 ms), but it has no public repositories, so a guest can't open an issues list there. The 10 ms figure is backed only by the query-count test, not by a timing on the preview.

Nit, no action needed for this review: the first paragraph of the pull description still says "50 mixed issues take under 10 ms (the best of five timed runs)". That timing assertion was replaced by the query count, so refresh the description on the next push.

Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs