perf(agent-manager): skip git stats polling for worktrees in collapsed sections (#8903)

Sync GitStatsPoller skip set with collapsed section state via pushState(),
saving 1 aheadBehind subprocess + 1 diffSummary HTTP call per hidden
worktree per poll cycle.

Closes #8900
This commit is contained in:
Marius
2026-04-15 10:59:55 +02:00
committed by GitHub
parent b9ecdb16a6
commit 0679fdfcd8
3 changed files with 31 additions and 4 deletions
@@ -789,6 +789,7 @@ export class AgentManagerProvider implements Disposable {
return null
}
// Remove from state BEFORE disk removal so pollers immediately stop targeting this worktree.
// Pre-emptive skip covers any in-flight poll that already captured getWorktrees().
this.statsPoller.skipWorktree(worktreeId)
this.prBridge.remove(worktreeId)
this.run.remove(worktreeId)
@@ -1251,6 +1252,18 @@ export class AgentManagerProvider implements Disposable {
}
}
/** Sync the poller's skip set with currently collapsed sections. */
private syncPollerSkips(): void {
const state = this.state
if (!state) return
const skipped = new Set<string>()
for (const sec of state.getSections()) {
if (!sec.collapsed) continue
for (const id of state.getWorktreesInSection(sec.id)) skipped.add(id)
}
this.statsPoller.syncSkips(skipped)
}
private pushState(): void {
const state = this.state
if (!state) return
@@ -1272,6 +1285,9 @@ export class AgentManagerProvider implements Disposable {
...run,
})
// Sync skip set before enabling the poller so the first poll cycle
// already excludes worktrees in collapsed sections.
this.syncPollerSkips()
this.statsPoller.setEnabled(worktrees.length > 0 || this.panel !== undefined)
this.prBridge.poller.setEnabled(worktrees.length > 0)
}
@@ -84,12 +84,14 @@ export class GitStatsPoller {
}
}
skipWorktree(id: string): void {
this.skipWorktreeIds.add(id)
/** Replace the entire skip set with the given IDs. */
syncSkips(ids: Set<string>): void {
this.skipWorktreeIds = ids
}
unskipWorktree(id: string): void {
this.skipWorktreeIds.delete(id)
/** Pre-emptively exclude a single worktree (e.g. before deletion). */
skipWorktree(id: string): void {
this.skipWorktreeIds.add(id)
}
setEnabled(enabled: boolean): void {
@@ -352,6 +352,15 @@ export class WorktreeStateManager {
return this.sections.get(id)
}
/** Return IDs of worktrees assigned to the given section. */
getWorktreesInSection(id: string): string[] {
const result: string[] = []
for (const wt of this.worktrees.values()) {
if (wt.sectionId === id) result.push(wt.id)
}
return result
}
addSection(name: string, color: string | null, worktreeIds?: string[]): Section {
this.setNormalizedWorktreeOrder(this.worktreeOrder)
const id = generateId("sec")