diff --git a/src/renderer/src/lib/legacy-worker-resume-fence-generation.ts b/src/renderer/src/lib/legacy-worker-resume-fence-generation.ts new file mode 100644 index 00000000000..172888721d7 --- /dev/null +++ b/src/renderer/src/lib/legacy-worker-resume-fence-generation.ts @@ -0,0 +1,12 @@ +// Why a separate module: hydration (inside the store) and the refresh (which writes the store) +// both bump it; keeping it import-free breaks the store → hydration → refresh → store cycle. +let generation = 0 + +/** A newer hydration or request makes every older in-flight fence reply stale. */ +export function advanceLegacyWorkerResumeFenceGeneration(): number { + return ++generation +} + +export function currentLegacyWorkerResumeFenceGeneration(): number { + return generation +} diff --git a/src/renderer/src/lib/legacy-worker-resume-fence-refresh.ts b/src/renderer/src/lib/legacy-worker-resume-fence-refresh.ts index e7ccee2983f..3325b98474d 100644 --- a/src/renderer/src/lib/legacy-worker-resume-fence-refresh.ts +++ b/src/renderer/src/lib/legacy-worker-resume-fence-refresh.ts @@ -1,14 +1,15 @@ -let generation = 0 -export function markLegacyWorkerResumeFencesHydrated(): void { - generation++ -} +import { useAppStore } from '@/store' +import { + advanceLegacyWorkerResumeFenceGeneration, + currentLegacyWorkerResumeFenceGeneration +} from './legacy-worker-resume-fence-generation' export async function refreshLegacyWorkerResumeFences(): Promise { - const requestGeneration = ++generation + const requestGeneration = advanceLegacyWorkerResumeFenceGeneration() try { const fences = await window.api.app.getLegacyWorkerResumeFences() - const { useAppStore } = await import('@/store') - if (requestGeneration !== generation) { + // A reply older than a later request or hydration describes state that has since been replaced. + if (requestGeneration !== currentLegacyWorkerResumeFenceGeneration()) { return } useAppStore.setState({ legacyWorkerResumeFencesByPaneKey: fences }) diff --git a/src/renderer/src/store/terminals/workspace-terminal-hydration.ts b/src/renderer/src/store/terminals/workspace-terminal-hydration.ts index d3c368d0d87..b558a65d798 100644 --- a/src/renderer/src/store/terminals/workspace-terminal-hydration.ts +++ b/src/renderer/src/store/terminals/workspace-terminal-hydration.ts @@ -1,4 +1,4 @@ -import { markLegacyWorkerResumeFencesHydrated } from '@/lib/legacy-worker-resume-fence-refresh' +import { advanceLegacyWorkerResumeFenceGeneration } from '@/lib/legacy-worker-resume-fence-generation' import { readWorkspaceSessionResumeFences } from '../../../../shared/workspace-session-resume-fences' import type { WorkspaceKey } from '../../../../shared/folder-workspace-types' import { FLOATING_TERMINAL_WORKTREE_ID } from '../../../../shared/constants' @@ -42,7 +42,7 @@ export function createWorkspaceTerminalHydrationActions( : null const ownershipTransfersByTabId = new Map() set((s) => { - markLegacyWorkerResumeFencesHydrated() + advanceLegacyWorkerResumeFenceGeneration() const runtimeSessionPlaceholders = buildRuntimeSessionPlaceholders({ repos: s.repos, runtimeHostIdByWorkspaceSessionKey: options?.runtimeHostIdByWorkspaceSessionKey ?? {},