Skip to content

Switch to the new worker first when a deploy changes the engine - #28

Closed
mike-doctorina wants to merge 1 commit into
fix/hardeningfrom
fix/engine-aware-update
Closed

mike-doctorina wants to merge 1 commit into
fix/hardeningfrom
fix/engine-aware-update

Conversation

@mike-doctorina

Copy link
Copy Markdown
Collaborator

Stacked on #27, merge after it.

Problem

On the first load after a deploy, the previous build's worker still controls the page:

  • it serves its cached main.dart.* cache-first;
  • index.html (network-first) and bootstrap.js (never intercepted) are already the new build's;
  • the bootstrap loads CanvasKit or skwasm for the new engineRevision.

On the same engine that mix runs, because flutter.js and the engine only change together with the Flutter SDK. After a Flutter upgrade it fails inside the engine (WebAssembly.instantiate(): Import #N). On a live deployment the same first load also waited out the full 4 s activation timeout before CanvasKit started.

Fix

  • Worker: reports its build's engineRevision in the getVersion reply. The generator writes it into the sw.js config, and only when the build has one.
  • Bootstrap (settleUpdateAtBootstrap, runs after registration and outside the 10 s registration cap):
    • It asks the controller for its engine revision, waiting at most 500 ms.
    • Same engine: the page boots with the current controller at once and the new worker takes over on the next load. registerAndActivate no longer waits 4 s for a worker that cannot activate while the page is open.
    • Different or unknown engine (workers from earlier releases don't report it, so the first load after upgrading takes this path once):
      • It waits up to 60 s (SW_UPDATE_INSTALL_TIMEOUT_MS) for the new worker to install. The precache progress is on screen through the existing sw-progress counter.
      • It then hands control to the new worker before any app file is requested.
      • If the handover is lost, it reloads once, with a sessionStorage guard against loops.
    • Failed or timed-out install: the page boots with its current controller, as it did before.

Verification

  • Playwright (e2e/engine-update.spec.ts, new): deploys the example twice over a local host, with a marker in main.dart.js.
    • Engine changed: the first load after the second deploy runs the new build. With the bootstrap's call to settleUpdateAtBootstrap removed it runs the old one (Expected "b", Received "a").
    • Same engine: the page boots with the old build at once and reaches the new one on a later load.
    • The new spec passed 10/10 with --repeat-each=5. The full suite passed, 19/19, run locally on installed Chrome.
  • Vitest: 303 pass, 12 of them new. 6 of the settleUpdateAtBootstrap tests fail against a stub.
  • Dart: 115 pass, integration included. analyze, format and npm run verify are clean.

Overlap with #25

This includes #25's first-load change: a controlled page no longer waits for a pending worker. It does not include #25's shorter 500 ms handover bound. When #25 is rebased, its registerAndActivate part reduces to the handover timeout.

On the first load after a deploy the previous worker still controls the
page and serves its cached main.dart.*, while index.html and bootstrap.js
are the new build's and the bootstrap loads the engine for the new
revision. On the same engine that mix runs; after a Flutter upgrade it
fails inside the engine.

The worker now reports its build's engineRevision on getVersion. The
bootstrap asks the controller for it:

- Same engine: boot with the controller at once, without the 4s
  activation wait it spent for nothing; the new worker takes over on
  the next load.
- Different or unknown engine (earlier workers don't report it): wait
  for the new worker to install, hand control to it before any app file
  is requested, and reload once if the handover is lost. A failed
  install leaves the page on its controller, as before.
@mike-doctorina

Copy link
Copy Markdown
Collaborator Author

Superseded by #31, which carries these commits unchanged plus the fixes for #30.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant