diff --git a/src/renderer/src/runtime/web-session-intent-owner.test.ts b/src/renderer/src/runtime/web-session-intent-owner.test.ts index 137b89ed991..dba9120cc04 100644 --- a/src/renderer/src/runtime/web-session-intent-owner.test.ts +++ b/src/renderer/src/runtime/web-session-intent-owner.test.ts @@ -11,6 +11,7 @@ import { resetWebSessionFocusIntentForTests } from './web-session-focus-intent' import { + MAX_REORDER_INTENT_PARTITIONS, recordWebSessionReorderIntent, resetWebSessionReorderIntentForTests, resolveWebSessionReorderedOrder @@ -28,6 +29,37 @@ afterEach(() => { }) describe('web session intent ownership', () => { + it('bounds unresolved reorder intent churn', () => { + for (let index = 0; index < MAX_REORDER_INTENT_PARTITIONS + 4; index += 1) { + recordWebSessionReorderIntent( + { environmentId: `env-${index}`, pairingRevision: 1 }, + WORKTREE_ID, + 'group-1', + ['tab-b', 'tab-a'], + 1_000 + ) + } + + expect( + resolveWebSessionReorderedOrder( + { environmentId: 'env-0', pairingRevision: 1 }, + WORKTREE_ID, + 'group-1', + ['tab-a', 'tab-b'], + 1_000 + ) + ).toEqual(['tab-a', 'tab-b']) + expect( + resolveWebSessionReorderedOrder( + { environmentId: `env-${MAX_REORDER_INTENT_PARTITIONS + 3}`, pairingRevision: 1 }, + WORKTREE_ID, + 'group-1', + ['tab-a', 'tab-b'], + 1_000 + ) + ).toEqual(['tab-b', 'tab-a']) + }) + it('isolates close intents across runtimes and same-id re-pairs', () => { recordWebSessionCloseIntent(OWNER_A, WORKTREE_ID, 'host-tab', 1_000) diff --git a/src/renderer/src/runtime/web-session-reorder-intent.ts b/src/renderer/src/runtime/web-session-reorder-intent.ts index 272ef635fa5..fe7d5d4b952 100644 --- a/src/renderer/src/runtime/web-session-reorder-intent.ts +++ b/src/renderer/src/runtime/web-session-reorder-intent.ts @@ -13,6 +13,8 @@ // rejected RPC) from pinning a stale order forever. const REORDER_INTENT_TTL_MS = 10_000 +export const MAX_REORDER_INTENT_PARTITIONS = 512 +export const MAX_REORDER_INTENTS_PER_PARTITION = 256 type ReorderIntent = { order: string[]; recordedAt: number } @@ -53,7 +55,24 @@ export function recordWebSessionReorderIntent( byGroup = new Map() pendingReorderByOwnerAndWorktree.set(partitionKey, byGroup) } + byGroup.delete(groupId) byGroup.set(groupId, { order: [...order], recordedAt: now }) + while (byGroup.size > MAX_REORDER_INTENTS_PER_PARTITION) { + const oldest = byGroup.keys().next() + if (oldest.done || oldest.value === groupId) { + break + } + byGroup.delete(oldest.value) + } + pendingReorderByOwnerAndWorktree.delete(partitionKey) + pendingReorderByOwnerAndWorktree.set(partitionKey, byGroup) + while (pendingReorderByOwnerAndWorktree.size > MAX_REORDER_INTENT_PARTITIONS) { + const oldest = pendingReorderByOwnerAndWorktree.keys().next() + if (oldest.done || oldest.value === partitionKey) { + break + } + pendingReorderByOwnerAndWorktree.delete(oldest.value) + } } /**