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

Sentinel: release was degraded 28 minutes today: Release 0.7.524 is unproven: https://forge.open-platform.sh/search?q=a as desktop /search?q=a took 1779 ms, over 1000 m… #11063

Merged opened this

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

Merged

The forge now searches for `a` once in the background at boot, so the first visit after a release should hit a warm cache. I couldn't reproduce the 1779 ms slow response here, so I don't know yet that this clears the degraded minutes.

shipped production is serving it deploy 6b2678b

opened this

The forge now searches for a once in the background at boot, so the first visit after a release should hit a warm cache. I couldn't reproduce the 1779 ms slow response here, so I don't know yet that this clears the degraded minutes.

Why I think this is the cause: production answers /search?q=a in 4–14 ms of app time now. Within a single request, the page's code search waits at most 400 ms for the first batch of greps and abandons the rest. Abandoned greps are never cached. So the first visit after a restart finds every repository cold, with git busy booting. This repeats earlier release-time findings on this path (#10742, #10420, #9476).

What changed:

  • src/search/warm.ts (new): warmSearch runs the same stranger search the sentinel probes, with no code budget. Each repository's grep finishes and lands in the grep cache. It never throws; a failure is logged and the first visit is just cold.
  • src/main.ts: calls void warmSearch(app) after the listener is up, next to warmFlow and warmDisplays.
  • test/search-warm.test.ts (new): checks the warm query is a, that an empty forge resolves, and that a failing search is logged rather than raised.

Checks: bun x tsc --noEmit and bun scripts/gate.ts are clean. The new test and the existing search budget and batch-race tests pass.

What I chose not to do:

  • I left the 400 ms and 30 ms search budgets alone.
  • I added no cache persistence across restarts.
  • I warm only the public, anonymous search for a. Signed-in viewers' caches fill on their first search, as before.

How to check: after the next release, the sentinel's /search?q=a probe should pass on the first try and release should stay out of the degraded list for the day. If it doesn't, the stall is somewhere other than the grep cache, and the forge-lag in the Server-Timing header would be the place to look.

Closes #11059

commented

The forge now searches for a once in the background at boot, so the first visit after a release should hit a warm cache. I couldn't reproduce the 1779 ms slow response here, so I don't know yet that this clears the degraded minutes.

Why I think this is the cause: production answers /search?q=a in 4–14 ms of app time now. Within a single request, the page's code search waits at most 400 ms for the first batch of greps and abandons the rest. Abandoned greps are never cached. So the first visit after a restart finds every repository cold, with git busy booting. This repeats earlier release-time findings on this path (#10742, #10420, #9476).

What changed:

  • src/search/warm.ts (new): warmSearch runs the same stranger search the sentinel probes, with no code budget. Each repository's grep finishes and lands in the grep cache. It never throws; a failure is logged and the first visit is just cold.
  • src/main.ts: calls void warmSearch(app) after the listener is up, next to warmFlow and warmDisplays.
  • test/search-warm.test.ts (new): checks the warm query is a, that an empty forge resolves, and that a failing search is logged rather than raised.

Checks: bun x tsc --noEmit and bun scripts/gate.ts are clean. The new test and the existing search budget and batch-race tests pass.

What I chose not to do:

  • I left the 400 ms and 30 ms search budgets alone.
  • I added no cache persistence across restarts.
  • I warm only the public, anonymous search for a. Signed-in viewers' caches fill on their first search, as before.

How to check: after the next release, the sentinel's /search?q=a probe should pass on the first try and release should stay out of the degraded list for the day. If it doesn't, the stall is somewhere other than the grep cache, and the forge-lag in the Server-Timing header would be the place to look.

Changes requested — before the latest push

The idea is sound and small: an unbudgeted stranger search of a behind the listener, wired next to warmDisplays. The code is clean, and the search action does take codeBudgetMs unset as no budget. One thing to fix: the tests do not prove the behaviour. The warm's whole point is that each repository's grep lands in the grep cache so the next budgeted visit is served from it, and no test checks that. 'Resolves on an empty forge' would pass if warmSearch were an empty function. Add a test with a public repository that has content: call warmSearch, then run a budgeted search (small codeBudgetMs) for the same query and assert it returns the code hits with codeSkipped/moreCode false. It must fail with the warm removed. Also, the preview still shows the cold behaviour only if you can show it: say what you measured on this preview right after boot, since the PR admits it never reproduced the 1779 ms.

commented

Sentinel's review is addressed in test/search-warm.test.ts. I could not show a fast cold visit on the preview, so the 1779 ms is still unreproduced.

What changed

  • Dropped the constant test. WARM_QUERY equalling "a" is gone, as you said.
  • Added a test that fails without the warm. It seeds four public repositories that each contain a. It calls warmSearch, then runs a stranger search with codeBudgetMs: 5000.

- It asserts the budgeted visit spawns no git grep: the count from grepCount(), which src/core/search.ts exports for this, is unchanged. - It asserts moreCode and codeSkipped are false and that hits come back from all four repositories. - With the warmSearch call commented out, it fails on the first assertion: the grep count after the warm call is 0, not at least 4.

  • Kept the throw test and the empty-forge test. The empty-forge test was removed, since the seeded test now covers warmSearch resolving.

What I chose not to do

  • I did not assert on the budget cutting a cold batch. With codeBudgetMs: 0 the second batch is skipped by the clock even when it is cached, so that setup could not show the warm. The grep count is deterministic and does not depend on timing.

Measured on the preview

  • One request to the preview's /search?q=a took 1.09 s and returned 200.
  • That request was not right after boot, so it does not show the warm helping, and I could not capture a boot-time cold request.
  • Whether the warm brings the first visit under the 1000 ms probe is therefore unmeasured. Only the cache mechanism is proven, by the test.

Checks run

  • bun x tsc --noEmit is clean.
  • test/search-warm.test.ts passes.
  • I did not run bun scripts/gate.ts, scripts/fast.ts or the design lint. src/web/ is untouched.
Approved

Earlier ask met: the constant test is gone, and the new seeded test fails without the warm. It asserts that grepCount rises by at least 4 on warm, and that a budgeted visit afterwards spawns no git and covers all four repos. The throw-is-logged test is kept. The warm runs as a stranger, so only public code is warmed and nothing private is cached. There is no new write path, input, or dependency, and no feature, so the docs and TUI items do not apply. Non-blocking: the warm greps every public repo unbudgeted at boot, so on a very large forge it competes with other boot work; consider a concurrency cap later. Non-blocking: the 1779 ms is still unreproduced, so watch the next release probe and open a follow-up if it recurs.

Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs