diff --git a/src/main/git/runner-wsl-direct-read.test.ts b/src/main/git/runner-wsl-direct-read.test.ts index e7ea423f78e..f57f18f2df0 100644 --- a/src/main/git/runner-wsl-direct-read.test.ts +++ b/src/main/git/runner-wsl-direct-read.test.ts @@ -28,6 +28,7 @@ import { import { disableWslGitReadEnvironment, getWslGitReadEnvironment, + peekWslGitReadEnvironment, resetWslGitReadEnvironmentForTests, seedWslGitReadEnvironmentForTests, WSL_GIT_READ_ENVIRONMENT_WAIT_MS @@ -167,6 +168,14 @@ describe('WSL direct Git reads', () => { } }) + it('bounds settled environment entries during distro churn', () => { + for (let index = 0; index < 132; index += 1) { + seedWslGitReadEnvironmentForTests(`distro-${index}`, LOGIN_ENVIRONMENT) + } + expect(peekWslGitReadEnvironment('distro-0')).toBeUndefined() + expect(peekWslGitReadEnvironment('distro-131')).toEqual(LOGIN_ENVIRONMENT) + }) + it('runs an opted-in read directly with translated cwd and arguments', async () => { await withPlatform('win32', async () => { seedWslGitReadEnvironmentForTests(DISTRO, LOGIN_ENVIRONMENT) diff --git a/src/main/git/wsl-git-read-environment.ts b/src/main/git/wsl-git-read-environment.ts index e75efee30d4..2027e9d3ed7 100644 --- a/src/main/git/wsl-git-read-environment.ts +++ b/src/main/git/wsl-git-read-environment.ts @@ -15,12 +15,30 @@ const PROBE_TIMEOUT_MS = 10_000 export const WSL_GIT_READ_ENVIRONMENT_WAIT_MS = 1_500 const PROBE_MAX_BUFFER = 64 * 1024 const TRANSIENT_PROBE_RETRY_MS = 30_000 +const MAX_WSL_GIT_READ_ENVIRONMENT_DISTROS = 128 const environmentByDistro = new Map>() // Why the null entries matter: a settled "no direct route" answer is what lets a read skip the // bounded probe wait entirely instead of racing an already-decided promise on every call. const settledEnvironmentByDistro = new Map() const transientRetryAfterByDistro = new Map() +function touchDistroState(distro: string): void { + const settled = settledEnvironmentByDistro.get(distro) + if (settledEnvironmentByDistro.has(distro)) { + settledEnvironmentByDistro.delete(distro) + settledEnvironmentByDistro.set(distro, settled ?? null) + } + while (settledEnvironmentByDistro.size > MAX_WSL_GIT_READ_ENVIRONMENT_DISTROS) { + const oldest = settledEnvironmentByDistro.keys().next().value + if (oldest === undefined) { + break + } + settledEnvironmentByDistro.delete(oldest) + environmentByDistro.delete(oldest) + transientRetryAfterByDistro.delete(oldest) + } +} + type ProbeOutcome = | { kind: 'resolved'; environment: WslGitReadEnvironment } | { kind: 'rejected' } @@ -95,10 +113,12 @@ export function getWslGitReadEnvironment(distro: string): Promise