Files
orca/src/main/wsl-directory-probe-command.ts
Neil d7d3114716 perf(wsl): single-flight the async WSL distro list (#17805)
On Windows, seven production call sites reach listWslDistrosAsync and on a cold
cache each spawned its own `wsl.exe --list --quiet` (5s timeout each): the
wsl:listDistros IPC behind the renderer capability read, the host.wsl.listDistros
RPC, the skill-install IPC, CLI registration reconciliation, the hook relay deps,
the kimi runtime home, plus relay preflight in the relay process. Concurrent
callers in one process now share one spawn.

Joining happens ahead of the negative cache, which also fixes a stranding bug: a
synchronous listWslDistros() landing an empty result mid-probe arms the 15s retry
window, and later async callers read that [] even though the pending probe is
about to see a distro that just finished provisioning. The non-empty-cache
short-circuit sits ahead of the join so a list already found synchronously is
still returned without waiting; that is main's existing behaviour preserved, not
a new fast path.

The shared promise cannot reject -- `catch` sits ahead of the stored promise, so
joiners get the same fail-safe [] the old per-caller catch returned -- and the
slot is cleared on settle, by the owning probe only.

wsl-directory-probe-command.ts is a verbatim move of the guest directory-probe
marker protocol and its parser out of wsl.ts, for oxlint max-lines headroom:
inlining it back makes wsl.ts 306 effective lines against a cap of 300. It takes
WslUncPathInfo from ../shared/wsl-paths -- the actual type of every value passed
at both call sites -- so it does not import from wsl.ts. _resetWslCachesForTests
and _setWslCachesForTests now share one resetWslDistroListState() instead of
repeating the same six assignments.

Per-platform delta:
- WSL on Windows: fewer wsl.exe spawns under startup fan-out, and a distro
  provisioned while a probe is pending is no longer hidden for the retry window.
- Native Windows without WSL: no behavioural change. The empty/failure retry
  windows, their backoff and the cache sequence guard are unchanged; N concurrent
  callers now cost one failed spawn instead of N.
- macOS, Linux, folder workspaces: no change. Both new early returns are
  unreachable off win32.
- SSH remote: no change for macOS/Linux hosts; a remote Windows host gets the
  Windows behaviour in its own process. No wire change -- host.wsl.listDistros
  keeps its string[] shape and its [] failure value.
- Relay: same single-flight inside the relay process. It stays per-process; the
  relay and main process still probe independently, as before.

Costs: a never-settling execFileUtf8 now pins the shared slot for the process
lifetime rather than only its own callers -- transient-to-permanent, not identical
exposure. And a joiner inherits the first probe's failure instead of making an
independent attempt.
2026-08-31 22:37:23 -07:00

34 lines
1.1 KiB
TypeScript

import type { WslUncPathInfo } from '../shared/wsl-paths'
// Why markers rather than an exit code: wsl.exe uses numeric exits for both guest results
// and host failures, so only a marker on stdout distinguishes "directory missing" from
// "wsl.exe could not answer".
const WSL_DIRECTORY_EXISTS_MARKER = '__ORCA_DIRECTORY_EXISTS__'
const WSL_DIRECTORY_MISSING_MARKER = '__ORCA_DIRECTORY_MISSING__'
/** Argv after the wsl.exe binary for the guest directory-existence probe. */
export function getWslDirectoryProbeArgs(info: WslUncPathInfo): string[] {
return [
'-d',
info.distro,
'--exec',
'sh',
'-c',
`if [ -d "$1" ]; then printf ${WSL_DIRECTORY_EXISTS_MARKER}; else printf ${WSL_DIRECTORY_MISSING_MARKER}; fi`,
'sh',
info.linuxPath
]
}
/** Null when neither marker appears, i.e. the guest never ran the test. */
export function parseWslDirectoryProbeOutput(stdout: unknown): boolean | null {
const output = String(stdout)
if (output.includes(WSL_DIRECTORY_EXISTS_MARKER)) {
return true
}
if (output.includes(WSL_DIRECTORY_MISSING_MARKER)) {
return false
}
return null
}