perf(agent-startup): skip unrelated store flushes (#8179)
This commit is contained in:
parent
0eafb0e626
commit
5eda948a7a
|
|
@ -0,0 +1,164 @@
|
|||
import { afterEach, describe, expect, it, vi } from 'vitest'
|
||||
import { useAppStore } from '@/store'
|
||||
import {
|
||||
queuePendingAgentStartupDelivery,
|
||||
resetAgentStartupDelayedDeliveryForTests
|
||||
} from './agent-startup-delayed-delivery'
|
||||
|
||||
const originalState = useAppStore.getState()
|
||||
const LEAF_ID = '11111111-1111-4111-8111-111111111111'
|
||||
|
||||
function seedPendingState(agentLaunchConfigByPaneKey: Record<string, unknown> = {}): void {
|
||||
useAppStore.setState({
|
||||
tabsByWorktree: {
|
||||
'wt-background': [
|
||||
{
|
||||
id: 'tab-background',
|
||||
ptyId: null,
|
||||
worktreeId: 'wt-background',
|
||||
title: 'Agent',
|
||||
customTitle: null,
|
||||
color: null,
|
||||
sortOrder: 0,
|
||||
createdAt: 1
|
||||
}
|
||||
]
|
||||
},
|
||||
pendingStartupByTabId: {
|
||||
'tab-background': { launchToken: 'target-launch' }
|
||||
},
|
||||
agentLaunchConfigByPaneKey,
|
||||
ptyIdsByTabId: { 'tab-background': [] },
|
||||
terminalLayoutsByTabId: {}
|
||||
} as never)
|
||||
}
|
||||
|
||||
function bindPendingPty(): void {
|
||||
useAppStore.setState({
|
||||
agentLaunchConfigByPaneKey: {
|
||||
[`tab-background:${LEAF_ID}`]: {
|
||||
identity: {
|
||||
tabId: 'tab-background',
|
||||
leafId: LEAF_ID,
|
||||
launchToken: 'target-launch'
|
||||
}
|
||||
}
|
||||
},
|
||||
ptyIdsByTabId: { 'tab-background': ['pty-background'] },
|
||||
terminalLayoutsByTabId: {
|
||||
'tab-background': {
|
||||
root: { type: 'leaf', leafId: LEAF_ID },
|
||||
activeLeafId: LEAF_ID,
|
||||
expandedLeafId: null,
|
||||
ptyIdsByLeafId: { [LEAF_ID]: 'pty-background' }
|
||||
}
|
||||
}
|
||||
} as never)
|
||||
}
|
||||
|
||||
function countedLaunchConfigs(count: number): {
|
||||
reads: { value: number }
|
||||
record: Record<string, unknown>
|
||||
} {
|
||||
const reads = { value: 0 }
|
||||
const record: Record<string, unknown> = {}
|
||||
for (let index = 0; index < count; index += 1) {
|
||||
Object.defineProperty(record, `other-pane-${index}`, {
|
||||
enumerable: true,
|
||||
get: () => {
|
||||
reads.value += 1
|
||||
return {
|
||||
identity: {
|
||||
tabId: `other-tab-${index}`,
|
||||
launchToken: `other-launch-${index}`
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
return { reads, record }
|
||||
}
|
||||
|
||||
afterEach(() => {
|
||||
resetAgentStartupDelayedDeliveryForTests()
|
||||
useAppStore.setState(originalState, true)
|
||||
})
|
||||
|
||||
describe('delayed agent startup subscription', () => {
|
||||
it('does not rescan launch metadata for unrelated store updates', () => {
|
||||
const launchConfigs = countedLaunchConfigs(500)
|
||||
seedPendingState(launchConfigs.record)
|
||||
|
||||
queuePendingAgentStartupDelivery({
|
||||
worktreeId: 'wt-background',
|
||||
tabId: 'tab-background',
|
||||
launchToken: 'target-launch',
|
||||
startup: {} as never,
|
||||
deliver: vi.fn()
|
||||
})
|
||||
expect(launchConfigs.reads.value).toBe(500)
|
||||
|
||||
launchConfigs.reads.value = 0
|
||||
for (let update = 0; update < 100; update += 1) {
|
||||
useAppStore.setState({ activeView: update % 2 === 0 ? 'terminal' : 'settings' } as never)
|
||||
}
|
||||
|
||||
expect(launchConfigs.reads.value).toBe(0)
|
||||
})
|
||||
|
||||
it('delivers when launch registration, PTY ownership, and layout binding arrive', () => {
|
||||
seedPendingState()
|
||||
const deliver = vi.fn().mockResolvedValue(undefined)
|
||||
const startup = {} as never
|
||||
queuePendingAgentStartupDelivery({
|
||||
worktreeId: 'wt-background',
|
||||
tabId: 'tab-background',
|
||||
launchToken: 'target-launch',
|
||||
startup,
|
||||
deliver
|
||||
})
|
||||
|
||||
bindPendingPty()
|
||||
|
||||
expect(deliver).toHaveBeenCalledWith('tab-background', 'pty-background', startup)
|
||||
})
|
||||
|
||||
it('drops a delivery when its tab is removed before PTY binding', () => {
|
||||
seedPendingState()
|
||||
const deliver = vi.fn().mockResolvedValue(undefined)
|
||||
queuePendingAgentStartupDelivery({
|
||||
worktreeId: 'wt-background',
|
||||
tabId: 'tab-background',
|
||||
launchToken: 'target-launch',
|
||||
startup: {} as never,
|
||||
deliver
|
||||
})
|
||||
|
||||
useAppStore.setState({ tabsByWorktree: {} })
|
||||
seedPendingState()
|
||||
bindPendingPty()
|
||||
|
||||
expect(deliver).not.toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('drops a delivery when a newer pending launch token replaces it', () => {
|
||||
seedPendingState()
|
||||
const deliver = vi.fn().mockResolvedValue(undefined)
|
||||
queuePendingAgentStartupDelivery({
|
||||
worktreeId: 'wt-background',
|
||||
tabId: 'tab-background',
|
||||
launchToken: 'target-launch',
|
||||
startup: {} as never,
|
||||
deliver
|
||||
})
|
||||
|
||||
useAppStore.setState({
|
||||
pendingStartupByTabId: {
|
||||
'tab-background': { launchToken: 'newer-launch' }
|
||||
}
|
||||
} as never)
|
||||
bindPendingPty()
|
||||
|
||||
expect(deliver).not.toHaveBeenCalled()
|
||||
})
|
||||
})
|
||||
|
|
@ -90,7 +90,33 @@ function ensurePendingAgentStartupSubscription(): void {
|
|||
if (unsubscribePendingAgentStartupDeliveries) {
|
||||
return
|
||||
}
|
||||
unsubscribePendingAgentStartupDeliveries = useAppStore.subscribe(() => {
|
||||
const initial = useAppStore.getState()
|
||||
// Capture the individual references so the gate stays allocation-free and
|
||||
// remains correct even if a subscribe adapter reuses its state object.
|
||||
let previousTabs = initial.tabsByWorktree
|
||||
let previousPendingStartups = initial.pendingStartupByTabId
|
||||
let previousLaunchConfigs = initial.agentLaunchConfigByPaneKey
|
||||
let previousPtyIds = initial.ptyIdsByTabId
|
||||
let previousLayouts = initial.terminalLayoutsByTabId
|
||||
unsubscribePendingAgentStartupDeliveries = useAppStore.subscribe((state) => {
|
||||
// Why: a background workspace can stay unmounted indefinitely. Only these
|
||||
// five immutable slices can change delivery eligibility; unrelated title,
|
||||
// status, focus, and usage ticks must not rescan every launch registration.
|
||||
if (
|
||||
state.tabsByWorktree === previousTabs &&
|
||||
state.pendingStartupByTabId === previousPendingStartups &&
|
||||
state.agentLaunchConfigByPaneKey === previousLaunchConfigs &&
|
||||
state.ptyIdsByTabId === previousPtyIds &&
|
||||
state.terminalLayoutsByTabId === previousLayouts
|
||||
) {
|
||||
return
|
||||
}
|
||||
// Update before flushing because delivery can synchronously write the store.
|
||||
previousTabs = state.tabsByWorktree
|
||||
previousPendingStartups = state.pendingStartupByTabId
|
||||
previousLaunchConfigs = state.agentLaunchConfigByPaneKey
|
||||
previousPtyIds = state.ptyIdsByTabId
|
||||
previousLayouts = state.terminalLayoutsByTabId
|
||||
flushPendingAgentStartupDeliveries()
|
||||
})
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue