diff --git a/src/main/wsl/wsl-host-focus-reachability.ts b/src/main/wsl/wsl-host-focus-reachability.ts new file mode 100644 index 00000000000..cfec17cd758 --- /dev/null +++ b/src/main/wsl/wsl-host-focus-reachability.ts @@ -0,0 +1,15 @@ +import type { WslHostConnector } from './wsl-host-service' + +/** + * Whether a focused host answers. Without a bridge in this process nothing answers yet, and focus + * connects whatever the running list says, so the WSL round trip would only delay the connect. + * Polls never use this: they must read the running list so they never boot a stopped distro (E9). + */ +export function focusReachability( + connector: Pick, + record: { distro: string; environmentId: string } +): ReturnType { + return connector.get(record.distro) + ? connector.reachability(record.distro, record.environmentId) + : Promise.resolve('unreachable') +} diff --git a/src/main/wsl/wsl-host-service.test.ts b/src/main/wsl/wsl-host-service.test.ts index 8fb53267679..6b6cdd56770 100644 --- a/src/main/wsl/wsl-host-service.test.ts +++ b/src/main/wsl/wsl-host-service.test.ts @@ -479,6 +479,39 @@ describe('WslHostService', () => { await vi.waitFor(() => expect(connector.connect).toHaveBeenCalledTimes(1)) }) + it('focus connects without probing WSL while this process has no bridge, but polls still read the running list', async () => { + const connector = makeConnector([UBUNTU]) + const service = makeService(connector) + await service.add({ distro: 'Ubuntu' }) + await connector.disconnect('Ubuntu') + connector.reachability.mockClear() + connector.connect.mockClear() + + service.focusHost('wsl:ubuntu') + await vi.waitFor(() => expect(connector.connect).toHaveBeenCalledTimes(1)) + expect(connector.reachability).not.toHaveBeenCalled() + + // A poll never takes that shortcut: it reads the running list and refuses a stopped distro. + await connector.disconnect('Ubuntu') + connector.distro.state = 'stopped' + connector.connect.mockClear() + await expect(service.ensureForRuntimeCall('wsl:ubuntu')).rejects.toThrow('Ubuntu was stopped') + expect(connector.reachability).toHaveBeenCalledWith('Ubuntu', 'wsl:ubuntu') + expect(connector.connect).not.toHaveBeenCalled() + }) + + it('focus with a bridge still asks whether the host answers before connecting again', async () => { + const connector = makeConnector([UBUNTU]) + const service = makeService(connector) + await service.add({ distro: 'Ubuntu' }) + connector.reachability.mockClear() + connector.connect.mockClear() + + service.focusHost('wsl:ubuntu') + await vi.waitFor(() => expect(connector.reachability).toHaveBeenCalledTimes(1)) + expect(connector.connect).not.toHaveBeenCalled() + }) + it('parks a host the moment a poll finds its distro confirmed stopped, never booting it', async () => { const connector = makeConnector([UBUNTU]) const service = makeService(connector) diff --git a/src/main/wsl/wsl-host-service.ts b/src/main/wsl/wsl-host-service.ts index aeea02b3b90..5d2ec7b19ec 100644 --- a/src/main/wsl/wsl-host-service.ts +++ b/src/main/wsl/wsl-host-service.ts @@ -4,6 +4,7 @@ * parked: polls and visible work keep it down until the user acts or the distro runs again. */ import { errorMessage } from '../../shared/error-message' +import { focusReachability } from './wsl-host-focus-reachability' import { removeWslHostEnvironment } from '../../shared/runtime-environment-wsl-host-store' import { readWslHostDeployments, @@ -293,8 +294,7 @@ export class WslHostService { return } this.parked.delete(record.environmentId) - void this.connector - .reachability(record.distro, record.environmentId) + void focusReachability(this.connector, record) .then((reachability) => reachability === 'available' ? undefined : this.connector?.connect(record.distro) )