feat(FN-4027): memoize startup slim list reads to avoid redundant fresh fet

Added memoization for startup slim task list reads (`store.ts`), with dashboard server routing startup reads through the memo window and tests covering the store watcher consumers in scheduler and worktree-pool, plus performance documentation.

Fusion-Task-Id: FN-4027
This commit is contained in:
Fusion
2026-05-11 18:36:53 -07:00
committed by gsxdsm
parent a22a665ec3
commit 5c3a1df977
9 changed files with 112 additions and 4 deletions

View File

@@ -1698,6 +1698,23 @@ describe("Scheduler", () => {
});
describe("pr monitoring", () => {
it("hydrates PR monitoring with startup memoized slim reads", async () => {
const prMonitor = {
startMonitoring: vi.fn(),
stopMonitoring: vi.fn(),
updatePrInfo: vi.fn(),
getTrackedPrs: vi.fn().mockReturnValue(new Map()),
stopAll: vi.fn(),
} as unknown as PrMonitor;
const store = createMockStore();
const scheduler = new Scheduler(store, {});
scheduler.configurePrMonitoring({ prMonitor });
await flushAsyncWork();
expect(store.listTasks).toHaveBeenCalledWith({ slim: true, includeArchived: false, startupMemo: true });
});
it("stops monitoring when task moves out of in-review based on from column", () => {
const prMonitor = {
startMonitoring: vi.fn(),

View File

@@ -576,6 +576,7 @@ describe("scanIdleWorktrees", () => {
const idle = await scanIdleWorktrees("/root", store);
expect(store.listTasks).toHaveBeenCalledWith({ slim: true, includeArchived: false, startupMemo: true });
expect(idle).toContain("/root/.worktrees/calm-river");
expect(idle).toContain("/root/.worktrees/bold-eagle");
expect(idle).not.toContain("/root/.worktrees/swift-falcon");

View File

@@ -516,7 +516,7 @@ export class Scheduler {
return;
}
void this.store.listTasks({ slim: true, includeArchived: false })
void this.store.listTasks({ slim: true, includeArchived: false, startupMemo: true })
.then((tasks) => {
const repo = getCurrentRepo(this.store.getRootDir());
if (!repo) return;

View File

@@ -304,7 +304,7 @@ export async function scanIdleWorktrees(rootDir: string, store: TaskStore): Prom
const registeredDirs = dirs.filter((dir) => registeredWorktrees.has(resolve(dir)));
// Find worktree paths assigned to non-done tasks (active worktrees)
const tasks = await store.listTasks({ slim: true, includeArchived: false });
const tasks = await store.listTasks({ slim: true, includeArchived: false, startupMemo: true });
const activeWorktrees = new Set<string>();
for (const task of tasks) {
if (task.worktree && task.column !== "done" && registeredWorktrees.has(resolve(task.worktree))) {