diff --git a/src/renderer/src/runtime/host-session-mirror-hydration-drain.test.ts b/src/renderer/src/runtime/host-session-mirror-hydration-drain.test.ts index 0b96e293c19..19738ffcb09 100644 --- a/src/renderer/src/runtime/host-session-mirror-hydration-drain.test.ts +++ b/src/renderer/src/runtime/host-session-mirror-hydration-drain.test.ts @@ -1,7 +1,9 @@ import { afterEach, describe, expect, it, vi } from 'vitest' import { clearRuntimeEnvironmentConnectionGenerationsForTests } from '@/store/slices/runtime-status' import { + getParkedHostSessionMirrorWaiterCountForTests, markHostSessionMirrorHydrated, + MAX_PARKED_HOST_SESSION_MIRROR_WAITERS, parkUntilHostSessionMirrorHydrates, resetHostSessionMirrorHydrationForTests } from './host-session-mirror-hydration' @@ -28,4 +30,14 @@ describe('host session mirror hydration drain', () => { expect(() => markHostSessionMirrorHydrated(ENVIRONMENT_ID)).not.toThrow() expect(secondReplay).toHaveBeenCalledTimes(1) }) + + it('bounds parked waiter growth when environments churn', () => { + for (let index = 0; index < MAX_PARKED_HOST_SESSION_MIRROR_WAITERS + 4; index += 1) { + parkUntilHostSessionMirrorHydrates(`env-${index}`, 'repo::worktree', () => {}) + } + + expect(getParkedHostSessionMirrorWaiterCountForTests()).toBe( + MAX_PARKED_HOST_SESSION_MIRROR_WAITERS + ) + }) }) diff --git a/src/renderer/src/runtime/host-session-mirror-hydration.ts b/src/renderer/src/runtime/host-session-mirror-hydration.ts index aaeb8685d73..93e23fc53d9 100644 --- a/src/renderer/src/runtime/host-session-mirror-hydration.ts +++ b/src/renderer/src/runtime/host-session-mirror-hydration.ts @@ -16,6 +16,7 @@ type ParkedMirrorWaiter = { environmentId: string; worktreeId: string; run: () = const hydratedGenerationByEnvironment = new Map() const hydratedGenerationByWorktree = new Map() const parkedWaitersByWorktree = new Map() +export const MAX_PARKED_HOST_SESSION_MIRROR_WAITERS = 512 function worktreeKey(environmentId: string, worktreeId: string): string { return `${environmentId}\0${worktreeId}` @@ -113,11 +114,24 @@ export function parkUntilHostSessionMirrorHydrates( worktreeId: string, run: () => void ): void { - parkedWaitersByWorktree.set(worktreeKey(environmentId, worktreeId), { + const key = worktreeKey(environmentId, worktreeId) + parkedWaitersByWorktree.delete(key) + parkedWaitersByWorktree.set(key, { environmentId, worktreeId, run }) + while (parkedWaitersByWorktree.size > MAX_PARKED_HOST_SESSION_MIRROR_WAITERS) { + const oldest = parkedWaitersByWorktree.keys().next() + if (oldest.done || oldest.value === key) { + break + } + parkedWaitersByWorktree.delete(oldest.value) + } +} + +export function getParkedHostSessionMirrorWaiterCountForTests(): number { + return parkedWaitersByWorktree.size } export function resetHostSessionMirrorHydrationForTests(): void {