mirror of
https://github.com/stablyai/orca.git
synced 2026-10-21 08:03:33 +00:00
perf(windows): route relay host-capability probes through the async wsl/pwsh twins
A paired web/mobile client resolves `useWindowsTerminalCapabilities` to a local
target (TabBar's `isWebClient` gate, and `useSettingsNavigationMetadata` forces
`{kind:'local'}`), so the new re-probe arms there too. But `window.api.wsl/pwsh`
on a web client is not the ipc/app.ts channel — it is `host.wsl.*`/`host.pwsh.*`
over the runtime RPC, which still ran the sync probes and blocked the desktop
main event loop on `execFileSync('wsl.exe' | 'pwsh.exe')` for up to 5s per call.
Switch those handlers and the relay preflight capability probe to the async
twins added here; they share the same caches, dedupe and backoff, so remote
callers see no behavior change.
This commit is contained in:
@@ -3,15 +3,31 @@ import { RpcDispatcher } from '../dispatcher'
|
||||
import type { RpcRequest } from '../core'
|
||||
import type { OrcaRuntimeService } from '../../orca-runtime'
|
||||
|
||||
const { isPwshAvailable, isWslAvailable, listWslDistros, isGitBashAvailable } = vi.hoisted(() => ({
|
||||
const {
|
||||
isPwshAvailable,
|
||||
isPwshAvailableAsync,
|
||||
isWslAvailable,
|
||||
isWslAvailableAsync,
|
||||
listWslDistros,
|
||||
listWslDistrosAsync,
|
||||
isGitBashAvailable
|
||||
} = vi.hoisted(() => ({
|
||||
isPwshAvailable: vi.fn(),
|
||||
isPwshAvailableAsync: vi.fn(),
|
||||
isWslAvailable: vi.fn(),
|
||||
isWslAvailableAsync: vi.fn(),
|
||||
listWslDistros: vi.fn(),
|
||||
listWslDistrosAsync: vi.fn(),
|
||||
isGitBashAvailable: vi.fn()
|
||||
}))
|
||||
|
||||
vi.mock('../../../pwsh', () => ({ isPwshAvailable }))
|
||||
vi.mock('../../../wsl', () => ({ isWslAvailable, listWslDistros }))
|
||||
vi.mock('../../../pwsh', () => ({ isPwshAvailable, isPwshAvailableAsync }))
|
||||
vi.mock('../../../wsl', () => ({
|
||||
isWslAvailable,
|
||||
isWslAvailableAsync,
|
||||
listWslDistros,
|
||||
listWslDistrosAsync
|
||||
}))
|
||||
vi.mock('../../../git-bash', () => ({ isGitBashAvailable }))
|
||||
|
||||
import { HOST_CAPABILITY_METHODS } from './host-capabilities'
|
||||
@@ -23,15 +39,18 @@ function makeRequest(method: string, params?: unknown): RpcRequest {
|
||||
describe('host capability RPC methods', () => {
|
||||
beforeEach(() => {
|
||||
isPwshAvailable.mockReset()
|
||||
isPwshAvailableAsync.mockReset()
|
||||
isWslAvailable.mockReset()
|
||||
isWslAvailableAsync.mockReset()
|
||||
listWslDistros.mockReset()
|
||||
listWslDistrosAsync.mockReset()
|
||||
isGitBashAvailable.mockReset()
|
||||
})
|
||||
|
||||
it('reports Windows shell capability probes through explicit methods', async () => {
|
||||
isPwshAvailable.mockReturnValue(true)
|
||||
isWslAvailable.mockReturnValue(true)
|
||||
listWslDistros.mockReturnValue(['Ubuntu'])
|
||||
isPwshAvailableAsync.mockResolvedValue(true)
|
||||
isWslAvailableAsync.mockResolvedValue(true)
|
||||
listWslDistrosAsync.mockResolvedValue(['Ubuntu'])
|
||||
isGitBashAvailable.mockReturnValue(true)
|
||||
const runtime = { getRuntimeId: () => 'test-runtime' } as unknown as OrcaRuntimeService
|
||||
const dispatcher = new RpcDispatcher({ runtime, methods: HOST_CAPABILITY_METHODS })
|
||||
@@ -55,4 +74,25 @@ describe('host capability RPC methods', () => {
|
||||
result: true
|
||||
})
|
||||
})
|
||||
|
||||
// Why: web/mobile clients reach these over the relay, so a sync probe would stall the
|
||||
// desktop main event loop on execFileSync wsl.exe/pwsh.exe for up to 5s per call.
|
||||
it('answers the Windows shell capability methods without a blocking spawn', async () => {
|
||||
isPwshAvailableAsync.mockResolvedValue(false)
|
||||
isWslAvailableAsync.mockResolvedValue(false)
|
||||
listWslDistrosAsync.mockResolvedValue([])
|
||||
const runtime = { getRuntimeId: () => 'test-runtime' } as unknown as OrcaRuntimeService
|
||||
const dispatcher = new RpcDispatcher({ runtime, methods: HOST_CAPABILITY_METHODS })
|
||||
|
||||
await dispatcher.dispatch(makeRequest('host.wsl.isAvailable'))
|
||||
await dispatcher.dispatch(makeRequest('host.wsl.listDistros'))
|
||||
await dispatcher.dispatch(makeRequest('host.pwsh.isAvailable'))
|
||||
|
||||
expect(isWslAvailableAsync).toHaveBeenCalledTimes(1)
|
||||
expect(listWslDistrosAsync).toHaveBeenCalledTimes(1)
|
||||
expect(isPwshAvailableAsync).toHaveBeenCalledTimes(1)
|
||||
expect(isWslAvailable).not.toHaveBeenCalled()
|
||||
expect(listWslDistros).not.toHaveBeenCalled()
|
||||
expect(isPwshAvailable).not.toHaveBeenCalled()
|
||||
})
|
||||
})
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { defineMethod, type RpcMethod } from '../core'
|
||||
import { isPwshAvailable } from '../../../pwsh'
|
||||
import { isWslAvailable, listWslDistros } from '../../../wsl'
|
||||
import { isPwshAvailableAsync } from '../../../pwsh'
|
||||
import { isWslAvailableAsync, listWslDistrosAsync } from '../../../wsl'
|
||||
import { isGitBashAvailable } from '../../../git-bash'
|
||||
|
||||
export const HOST_CAPABILITY_METHODS: RpcMethod[] = [
|
||||
@@ -9,20 +9,22 @@ export const HOST_CAPABILITY_METHODS: RpcMethod[] = [
|
||||
params: null,
|
||||
handler: async () => ({ platform: process.platform })
|
||||
}),
|
||||
// Why: paired web/mobile clients route capability reads here, so a sync probe would
|
||||
// execFileSync wsl.exe/pwsh.exe on this host's main event loop for up to 5s per call.
|
||||
defineMethod({
|
||||
name: 'host.wsl.isAvailable',
|
||||
params: null,
|
||||
handler: async () => isWslAvailable()
|
||||
handler: async () => isWslAvailableAsync()
|
||||
}),
|
||||
defineMethod({
|
||||
name: 'host.wsl.listDistros',
|
||||
params: null,
|
||||
handler: async () => listWslDistros()
|
||||
handler: async () => listWslDistrosAsync()
|
||||
}),
|
||||
defineMethod({
|
||||
name: 'host.pwsh.isAvailable',
|
||||
params: null,
|
||||
handler: async () => isPwshAvailable()
|
||||
handler: async () => isPwshAvailableAsync()
|
||||
}),
|
||||
defineMethod({
|
||||
name: 'host.gitBash.isAvailable',
|
||||
|
||||
@@ -5,13 +5,17 @@ const { execFileAsyncMock } = vi.hoisted(() => ({
|
||||
execFileAsyncMock: vi.fn()
|
||||
}))
|
||||
|
||||
const { isPwshAvailableMock, isWslAvailableMock, listWslDistrosMock, isGitBashAvailableMock } =
|
||||
vi.hoisted(() => ({
|
||||
isPwshAvailableMock: vi.fn(),
|
||||
isWslAvailableMock: vi.fn(),
|
||||
listWslDistrosMock: vi.fn(),
|
||||
isGitBashAvailableMock: vi.fn()
|
||||
}))
|
||||
const {
|
||||
isPwshAvailableAsyncMock,
|
||||
isWslAvailableAsyncMock,
|
||||
listWslDistrosAsyncMock,
|
||||
isGitBashAvailableMock
|
||||
} = vi.hoisted(() => ({
|
||||
isPwshAvailableAsyncMock: vi.fn(),
|
||||
isWslAvailableAsyncMock: vi.fn(),
|
||||
listWslDistrosAsyncMock: vi.fn(),
|
||||
isGitBashAvailableMock: vi.fn()
|
||||
}))
|
||||
|
||||
vi.mock('child_process', () => {
|
||||
const execFileWithPromisify = Object.assign(vi.fn(), {
|
||||
@@ -20,10 +24,10 @@ vi.mock('child_process', () => {
|
||||
return { execFile: execFileWithPromisify }
|
||||
})
|
||||
|
||||
vi.mock('../main/pwsh', () => ({ isPwshAvailable: isPwshAvailableMock }))
|
||||
vi.mock('../main/pwsh', () => ({ isPwshAvailableAsync: isPwshAvailableAsyncMock }))
|
||||
vi.mock('../main/wsl', () => ({
|
||||
isWslAvailable: isWslAvailableMock,
|
||||
listWslDistros: listWslDistrosMock
|
||||
isWslAvailableAsync: isWslAvailableAsyncMock,
|
||||
listWslDistrosAsync: listWslDistrosAsyncMock
|
||||
}))
|
||||
vi.mock('../main/git-bash', () => ({ isGitBashAvailable: isGitBashAvailableMock }))
|
||||
|
||||
@@ -61,9 +65,9 @@ function fishLookupArgs(command: string): string[] {
|
||||
|
||||
beforeEach(() => {
|
||||
execFileAsyncMock.mockReset()
|
||||
isPwshAvailableMock.mockReset()
|
||||
isWslAvailableMock.mockReset()
|
||||
listWslDistrosMock.mockReset()
|
||||
isPwshAvailableAsyncMock.mockReset()
|
||||
isWslAvailableAsyncMock.mockReset()
|
||||
listWslDistrosAsyncMock.mockReset()
|
||||
isGitBashAvailableMock.mockReset()
|
||||
})
|
||||
|
||||
@@ -319,9 +323,9 @@ describe('PreflightHandler', () => {
|
||||
configurable: true,
|
||||
value: 'win32'
|
||||
})
|
||||
isWslAvailableMock.mockReturnValue(true)
|
||||
listWslDistrosMock.mockReturnValue(['Ubuntu'])
|
||||
isPwshAvailableMock.mockReturnValue(true)
|
||||
isWslAvailableAsyncMock.mockResolvedValue(true)
|
||||
listWslDistrosAsyncMock.mockResolvedValue(['Ubuntu'])
|
||||
isPwshAvailableAsyncMock.mockResolvedValue(true)
|
||||
isGitBashAvailableMock.mockReturnValue(true)
|
||||
|
||||
const requestHandlers = new Map<string, (params: Record<string, unknown>) => Promise<unknown>>()
|
||||
|
||||
@@ -4,8 +4,8 @@ import { promisify } from 'node:util'
|
||||
import path, { win32 } from 'node:path'
|
||||
import type { RelayDispatcher } from './dispatcher'
|
||||
import { buildRelayCommandEnv } from './relay-command-env'
|
||||
import { isPwshAvailable } from '../main/pwsh'
|
||||
import { isWslAvailable, listWslDistros } from '../main/wsl'
|
||||
import { isPwshAvailableAsync } from '../main/pwsh'
|
||||
import { isWslAvailableAsync, listWslDistrosAsync } from '../main/wsl'
|
||||
import { isGitBashAvailable } from '../main/git-bash'
|
||||
import { buildPosixCommandPathLookupScript } from '../shared/posix-command-path-lookup'
|
||||
|
||||
@@ -101,11 +101,11 @@ export class PreflightHandler {
|
||||
hostPlatform: NodeJS.Platform | null
|
||||
}> {
|
||||
const [wslAvailable, pwshAvailable, gitBashAvailable] = await Promise.all([
|
||||
Promise.resolve(isWslAvailable()).catch(() => false),
|
||||
Promise.resolve(isPwshAvailable()).catch(() => false),
|
||||
isWslAvailableAsync().catch(() => false),
|
||||
isPwshAvailableAsync().catch(() => false),
|
||||
Promise.resolve(isGitBashAvailable()).catch(() => false)
|
||||
])
|
||||
const wslDistros = wslAvailable ? await Promise.resolve(listWslDistros()).catch(() => []) : []
|
||||
const wslDistros = wslAvailable ? await listWslDistrosAsync().catch(() => []) : []
|
||||
return {
|
||||
wslAvailable,
|
||||
wslDistros,
|
||||
|
||||
Reference in New Issue
Block a user