Skip to content

[WIP] test(e2e): reuse one runtime per worker + shared readiness helper (Tier 2)#9607

Open
nishantmonu51 wants to merge 4 commits into
mainfrom
nishant/e2e-runtime-reuse
Open

[WIP] test(e2e): reuse one runtime per worker + shared readiness helper (Tier 2)#9607
nishantmonu51 wants to merge 4 commits into
mainfrom
nishant/e2e-runtime-reuse

Conversation

@nishantmonu51

Copy link
Copy Markdown
Collaborator

Tier 2 of the e2e performance & flakiness work (follow-up to #9596). Keeps workers: 1 for now; horizontal sharding is deferred.

  • Reuse the rill binary across tests instead of respawning per test. The web-common rillDev fixture now starts rill once per Playwright worker (scope: "worker") and resets the project between tests rather than killing the process. This eliminates ~one binary spawn per test and the controller closed / readonly database DuckDB teardown races that came with it.
  • The reset clears the previous project's source files but preserves rill.yaml (deleting it orphans the parser's resources) and the runtime's tmp/ DB dir (the open DuckDB can't be wiped). It then waits for the old resources to tear down, copies the new project, and waits for full reconciliation. Two runtime behaviours discovered while validating this are documented in code: the ProjectParser stays RUNNING while watching the repo (so readiness keys on data resources only), and deleting rill.yaml leaves resources orphaned.
  • Tests that need an uninitialized/pristine project (the welcome flow: init, rill-yaml empty-project, motherduck) opt out via a new freshInstance fixture option.
  • Promote waitForReconciliation into web-common/tests/utils and add gotoWhenReady. The fixture now gates every test start on full reconciliation instead of a fixed waitForTimeout(1500), addressing the recurring navigate-before-reconcile flakiness centrally.
  • Delete the unused startRuntimeForEachTest.ts.

Local validation (workers: 1): a 16-test subset spanning BlankAdBids transitions with heavy file mutation ran with 1 binary spawn (was ~16) and zero controller closed / readonly database teardown races; a mixed shared + freshInstance batch also passed.

Not included: Tier 2 workers/sharding (deferred per request — workers: 1 retained) and the web-admin describe.serial blast-radius reduction. The latter is deferred because those blocks are legitimate create→apply→delete lifecycles sharing one explore; the spec's own TODO notes per-feature explores are needed first, and adminPage can't be used in beforeAll. Decoupling them blind would introduce conflicts.

Checklist:

  • Covered by tests
  • Ran it and it works as intended
  • Reviewed the diff before requesting a review
  • Checked for unhandled edge cases
  • Linked the issues it closes
  • Checked if the docs need to be updated. If so, create a separate Linear DOCS issue
  • Intend to cherry-pick into the release branch
  • I'm proud of this work!

Developed in collaboration with Claude Code

…er 2)

Reuse the rill binary across tests instead of respawning per test:
- web-common rillDev fixture now starts rill once per Playwright worker
  (scope: worker) and resets the project between tests rather than killing
  the process. Reset clears the previous project's source files (preserving
  rill.yaml and the runtime's tmp/ DB dir, since deleting rill.yaml orphans
  resources and an open DuckDB can't be wiped), waits for the old resources
  to tear down, copies the new project, then waits for full reconciliation.
- Tests needing an uninitialized/pristine project (welcome flow: init,
  rill-yaml empty-project, motherduck) opt out via a new freshInstance option.
- Promote waitForReconciliation into web-common/tests/utils and add
  gotoWhenReady; the fixture now gates every test start on reconciliation
  instead of a fixed waitForTimeout(1500). Repoint the 5 importers.
- Delete the unused startRuntimeForEachTest.ts.

workers stays 1 (Tier 2 sharding deferred). Local validation: a 16-test
subset across Blank/AdBids transitions with file mutation ran with 1 binary
spawn (was ~16) and zero controller-closed/readonly-database teardown races.
- clickhouse/postgres connectors: mark freshInstance. They drive the
  welcome flow (needs an uninitialized project) and clickhouse restarts the
  controller by changing olap_connector — both incompatible with the shared
  per-worker runtime. Fixes the two web-local failures.
- waitForProjectReady: key stability on resource names only, not
  stateVersion. A resource that re-reconciles back to idle (common during a
  deploy) was resetting the stability counter and stalling readiness, which
  failed web-integration with 'did not become ready' and no pending resources.
- cliHomeDir: default to undefined and route any test that sets it to its own
  instance. The deploy journey relies on CLI auth state in a specific home,
  which the shared runtime's worker home would not provide.
… deploy churn

- clickhouse/postgres: move freshInstance onto only the 'Welcome screen'
  blocks (which need an uninitialized project). The 'Home page' blocks stay
  on the shared runtime — they passed there, and the per-test reset recovers
  the controller restart that clickhouse's olap_connector change triggers.
  Marking the whole describe freshInstance had regressed the Home page tests.
- waitForProjectReady: if the resource set never stabilizes within the
  timeout but the project did reach a fully-idle state, proceed instead of
  failing. The deploy tests' background cloud sync churns the resource set
  continuously, which previously failed with 'did not become ready (none
  pending)'.

Validated locally: clickhouse welcome (fresh) + home page (shared) + a
trailing shared spec all pass, confirming the olap change doesn't corrupt
the reused runtime.
The per-test (freshInstance) path copies the project into its dir, but
startRuntime then rmSync'd that dir before spawning, leaving the runtime with
an empty project. This only surfaced for freshInstance tests that use a
project (the deploy journey: freshInstance via cliHomeDir + project=AdBids);
the welcome-flow freshInstance tests use no project so an empty dir was
correct. startRuntime now assumes the caller prepared projectDir.

Validated locally: a freshInstance + project:AdBids instance now loads the
project's resources (waitForProjectReady no longer times out on an empty
project).
@nishantmonu51 nishantmonu51 changed the title test(e2e): reuse one runtime per worker + shared readiness helper (Tier 2) [WIP] test(e2e): reuse one runtime per worker + shared readiness helper (Tier 2) Jun 25, 2026
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