Repository navigation
Studio: Apply site events to the site list instead of refetching it - #5506
Merged
Merged
Conversation
Collaborator
📊 Performance Test ResultsComparing bac99cf vs trunk app-size
site-editor
site-startup
Results are median values from multiple test runs. Legend: 🟢 Improvement (faster) | 🔴 Regression (slower) | ⚪ No change (<50ms diff) |
…ges made during the status sweep
1 task done
Contributor
|
Thanks for reworking the approach here. |
Contributor
Author
|
Massive performance gains over the past couple of weeks! |
chubes4
added a commit
that referenced
this pull request
Oct 28, 2026
#5512) ## Related issues - Related to #5495 and #5506 (site start and creation timing). ## How AI was used in this PR Claude (via the Pi coding agent in a Roadie session) traced each step of `site create`, wrote the change and the test, and ran the A/B timings below. I reviewed the diff and the measurements. ## Proposed Changes When a site is created, the first start installs WordPress with `wp core install`, which creates the admin user with the configured username, password and email. The same start then sends those credentials again to the site's admin API (`set_admin_password`). That request is a full WordPress load plus a `wp_check_password` against the bcrypt hash the installer just wrote. On my machine it took 250–290 ms, and it changes nothing. - `installWordPress` now returns whether it ran the installer. - `startServer` skips the credentials request when the installer ran on this start and no Blueprint ran after it. A Blueprint can change users, so Blueprint creates still apply the credentials afterwards. - Every other start is unchanged. Restarts still apply credentials, so a password changed while a site was stopped still takes effect on its next start. Measured with the built CLI on macOS, alternating trunk and this branch, from `Checking PHP binary…` to `WordPress server started` during `site create`: | | runs | median | |---|---|---| | trunk | 8 | 2,127 ms | | this branch | 8 | 1,808 ms | This branch was faster in all 8 pairs (−319 ms median). Local timings on a busy machine, so CI's `siteCreation` metric is the number to trust. ## Testing Instructions - `npm run cli:build` - `npm test -- --tagsFilter='e2e' apps/cli/commands/site/tests/create.e2e.test.ts` - The create e2e test now creates a site with `--admin-username navigator --admin-password e2e-created-password` and signs in to `wp-login.php` with them. It fails if the installer doesn't set the credentials the start no longer re-applies (checked by making the installer ignore `adminUsername`). - `site-management.e2e.test.ts` still covers changing the password on an existing site and signing in with it. - Manually: `node apps/cli/dist/cli/main.mjs site create --path ~/Studio/creds-check --admin-password secret123 --skip-browser`, then sign in at `/wp-admin` as `admin` / `secret123`. ## Pre-merge Checklist - [x] Have you checked for TypeScript, React or other console errors?
1 task done
chubes4
added a commit
that referenced
this pull request
Oct 28, 2026
…metry lets the process exit (#5522) ## Related issues - Related to #5512 and #5506 (site creation timing). ## How AI was used in this PR Claude (via the Pi coding agent in a Roadie session) traced where the app waits on the CLI, wrote the change and the tests, and measured the timings below. I reviewed the diff and the measurements. ## Proposed Changes The app treats a CLI command as finished when its process exits. After `site create` finishes, it sends a Tracks event, and Node keeps the process alive until that request completes. So the create flow waits on a telemetry request after the site is ready. - The CLI sends a `done` message once a command has finished successfully, from one place after the command handler returns (`apps/cli/index.ts`). - `runCliCommand` resolves on that message, and still on exit for anything that doesn't send it. Failures still wait for the exit and reject with the command's error. - Site start, stop and delete keep finishing on exit for now. Their tail is smaller and they need a separate look. - The process keeps running in the background until the request completes, so no events or stats are lost. - `site create` reports its result before an import finishes, so `runCliCommand` keeps resolving with that result but only once `done` arrives. - The preview manager ignores the new message instead of logging it as an invalid event. Measured with a production CLI build forked over IPC like the app does, with telemetry on, time from `done` to the process exiting: | command | runs | time after `done` | |---|---|---| | `site create` | 5 | 338–421 ms | | `site start` / `stop`, telemetry opted out | 3 each | 7–9 ms | That is the time the app no longer waits. It depends on the user's latency to WordPress.com; these numbers are from a fast connection. CI's performance metrics won't show it, because Tracks requests are skipped in E2E runs. ## Testing Instructions - `npm test -- packages/common/lib/tests/cli-process.test.ts` - The new test resolves a create from a command that reports `done` and never exits. It times out without this change. - Manually, in a packaged build with analytics on: create a site, and the app shows it as created as soon as the CLI reports it. ## Pre-merge Checklist - [x] Have you checked for TypeScript, React or other console errors?
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Related issues
How AI was used
Claude (via the Pi coding agent in a Roadie session) traced the start path, wrote the change and its tests, checked the tests by reverting each piece, and counted the
site listcalls in packaged builds. I reviewed the diff and the evidence.Proposed Changes
Every site event the renderer received made it invalidate the site list. Each refetch spawns a CLI
site list, which takes about 300 ms. A start or stop sends several events and also awaited one more refetch of its own. Yet eachsite-updatedandsite-operations-changedevent already carries the site's full record.use-sites.ts): writes the event's site into the TanStack Query cache withsetQueryData, asuseUpdateSitesSortOrderalready does. It keeps the two fields only Studio stores (sortOrder,autoStart).satisfiesties those toSiteMetadata, so a new metadata field won't compile until it's carried over. Asite-operations-changedevent keeps the cachedrunning, because it doesn't know whether the site runs.getSitesknows. Its events now go out without the CLI's details, so the renderer refetches for them as before.site listand the events now build the site from onegetSiteDetails. Until now the events left outemailPath, so an applied event would have dropped it.Applying events directly, rather than refetching on each one, exposed two gaps that the refetches had been covering up:
isFetchedAfterMount. That flag also turns true when an event is applied on top of the list persisted from the last launch, which predates theautoStartflags the quit set. Auto-start now reads the list itself withfetchQuery, which joins the launch fetch already in flight._eventsread every site's status before subscribing to the process manager. A site that finished starting in between never got an event. It now subscribes first, so the last event for a site reflects its current state.No new cache layer: TanStack Query stays the only one.
In packaged builds, I counted
site listcalls through a probe in the CLI entry. A run of the startup metric (one creation plus five starts and stops) made 33 calls on trunk and 10–16 with this change, across three runs each. Calls only remain where a fallback refetch is needed, for example when an operation's release lands after the start has resolved. Local timings were unusable because the machine's load average was 20–30. The Performance Metrics job is the timing check.Testing Instructions
npx vitest run apps/ui/src/data/queries/use-sites.test.tsx apps/studio/src/modules/cli/lib/tests/cli-events-subscriber.test.ts apps/cli/commands/site/tests/list.test.tsisFetchedAfterMountgate.runningfor operation events, the kept metadata, or the skipped refetches.wp-config.phpand start it. It shows the PHP error page at its URL, as before.Pre-merge Checklist