Skip to content

perf(cli): upgrade check delays fast commands when registry response is slow #2234

Description

@leslieeilsel

Describe the bug

On commit a24eede77ebec23b3e942437bda34f6d34a95cd3, a fast interactive command such as vp env list normally completes within a few milliseconds on my machine. When the configured npm registry responds slowly, the same command consistently takes roughly half a second.

If the upgrade request is still pending when the command exits, the upgrade check cache is not written. The next invocation performs the same request and experiences the same delay again.

I reproduced this with five consecutive invocations. Each invocation made a new registry request, and .upgrade-check.json remained absent.

Expected behavior: a pending upgrade check should not noticeably delay command exit or cause the same registry request on every subsequent invocation.

Reproduction

https://github.com/voidzero-dev/vite-plus/tree/a24eede77ebec23b3e942437bda34f6d34a95cd3

Steps to reproduce

1. Build the release CLI

cargo build -p vite_global_cli --release --locked

2. Start a local registry that responds after two seconds

Run this in a separate terminal:

node - <<'JS'
const http = require('node:http');

const body = JSON.stringify({
  version: '999.0.0',
  dist: {
    tarball: '',
    integrity: '',
  },
});

http
  .createServer((request, response) => {
    console.log('request:', request.url);

    setTimeout(() => {
      if (response.destroyed) return;

      response.writeHead(200, {
        'content-type': 'application/json',
        'content-length': Buffer.byteLength(body),
      });
      response.end(body);
    }, 2_000);
  })
  .listen(48_731, '127.0.0.1', () => {
    console.log('Local registry listening on http://127.0.0.1:48731');
  });
JS

3. Configure an isolated test environment

Run this from the Vite+ repository in an interactive terminal:

export VP_HOME="$(mktemp -d)"
export NPM_CONFIG_REGISTRY="http://127.0.0.1:48731"

unset CI
unset VP_CLI_TEST
unset VP_NO_UPDATE_CHECK

The test must run in an interactive terminal because the upgrade check is skipped when stderr is not a TTY.

4. Establish a baseline

Warm up the binary once, then measure it with the upgrade check disabled:

VP_NO_UPDATE_CHECK=1 target/release/vp env list >/dev/null
time VP_NO_UPDATE_CHECK=1 target/release/vp env list

On my machine, the command normally completes within a few milliseconds after warm-up.

5. Run the command repeatedly with the delayed registry

for run in 1 2 3 4 5; do
  echo "Run $run"
  time target/release/vp env list
done

Each invocation takes roughly half a second, and the registry terminal prints a new request for every invocation.

6. Inspect the cache

test -f "$VP_HOME/.upgrade-check.json" \
  && cat "$VP_HOME/.upgrade-check.json" \
  || echo "cache missing"

Observed output:

cache missing

System Info

Device: Mac mini
Chip: Apple M4, 10-core
Memory: 16 GB
OS: macOS 27.0, arm64

Vite+ commit: a24eede77ebec23b3e942437bda34f6d34a95cd3
vp: 0.2.6, release build
Rust: 1.98.0-nightly
Node.js: 22.18.0
Package manager: pnpm 10.34.4

Used Package Manager

pnpm

Logs

Baseline after warm-up: a few milliseconds
Delayed registry: roughly half a second per invocation
Registry requests: one new request per invocation
Upgrade check cache after five invocations: missing

Validations

  • Read the Contributing Guidelines.
  • Checked open and closed issues for the same bug.
  • Checked open pull requests for an existing fix.
  • Confirmed this behavior is in Vite+ rather than an upstream tool.
  • Provided a self-contained reproduction.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    Fields

    Priority

    None yet

    Effort

    None yet

    Target date

    None yet

    Start date

    None yet

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions