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

A look waits for the app to answer its health check before the first picture #11653

Merged opened this

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

Merged

A look now waits for the app to answer before it opens a browser. An app that answers late gets one capture pass, and one that never answers gets no capture and a recorded reason.

shipped production is serving it deploy 99a34f7

opened this

A look now waits for the app to answer before it opens a browser. An app that answers late gets one capture pass, and one that never answers gets no capture and a recorded reason.

  • The wait: In src/looks/service.ts, take() polls the app's port every 250 ms for up to 5 s once it knows which pictures are missing. Any reply below HTTP 500 counts as answering.
  • Never answers: No capture runs. Each wanted picture is recorded with the error NOT_ANSWERING ("the app did not answer its health check in time") and an empty path. The look then goes through the existing #11509 backoff.
  • For tests: startLooks takes answers, answerWaitMs and answerPollMs so a test can control the wait.
  • Test: In test/looks.test.ts, an app that answers on its fourth ask gets its captures and no failure rows. An app that never answers gets zero capture calls and NOT_ANSWERING on every row.

Checks.

  • tsc and scripts/gate.ts are clean.
  • test/looks.test.ts shows 25 passes and 3 failures. The failures are the real-Chromium tests, which fail identically without this change because the sandbox blocks the browser's socket(). The forge check will run them.
  • I also ran test/looks-owner, test/preview-looks and test/main-looks after the change. Their failures looked the same as before, but I couldn't finish a with/without comparison for them.

Left out:

  • Health path: The probe asks /, not the manifest's app.health, because the environment status doesn't carry that path. A deploy already checks both before it serves, so / is enough here.
  • Timing: The wait isn't configurable per app.

Try it: run bun test test/looks.test.ts -t "waits for the app".

Closes #11520

commented

A look now waits for the app to answer before it opens a browser. An app that answers late gets one capture pass, and one that never answers gets no capture and a recorded reason.

  • The wait: In src/looks/service.ts, take() polls the app's port every 250 ms for up to 5 s once it knows which pictures are missing. Any reply below HTTP 500 counts as answering.
  • Never answers: No capture runs. Each wanted picture is recorded with the error NOT_ANSWERING ("the app did not answer its health check in time") and an empty path. The look then goes through the existing #11509 backoff.
  • For tests: startLooks takes answers, answerWaitMs and answerPollMs so a test can control the wait.
  • Test: In test/looks.test.ts, an app that answers on its fourth ask gets its captures and no failure rows. An app that never answers gets zero capture calls and NOT_ANSWERING on every row.

Checks.

  • tsc and scripts/gate.ts are clean.
  • test/looks.test.ts shows 25 passes and 3 failures. The failures are the real-Chromium tests, which fail identically without this change because the sandbox blocks the browser's socket(). The forge check will run them.
  • I also ran test/looks-owner, test/preview-looks and test/main-looks after the change. Their failures looked the same as before, but I couldn't finish a with/without comparison for them.

Left out:

  • Health path: The probe asks /, not the manifest's app.health, because the environment status doesn't carry that path. A deploy already checks both before it serves, so / is enough here.
  • Timing: The wait isn't configurable per app.

Try it: run bun test test/looks.test.ts -t "waits for the app".

Approved

Approved. A look now waits, bounded, for the app to answer before opening a browser, and records one reason when it never does. The test covers both the late answer and the mute app, and the probe, error path, and backoff reuse the existing shape. No new dependency, no README change, and the change reaches no page or terminal surface. Nothing here touches the experience for a person: no layout, keyboard, or phone-width effect.

Two things I would do next:

  1. Probe the manifest app.health path instead of /, so an app whose root redirects to a broken page is not counted as answering. Also bound the total wait: a 2 s fetch timeout on top of the 5 s wait can overshoot to about 7 s.
  2. Where the status has no port, the wait is skipped silently. Log that case so it is visible. Also, the direction is pipeline first and this is a looks fix; keep the next pull on the pipeline list.
Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs