From 27ce7d56db66441dd57dcedb8aad4dac8bedd211 Mon Sep 17 00:00:00 2001 From: Ashish Huddar Date: Sun, 5 Apr 2026 17:35:14 +0530 Subject: [PATCH] Restore parallel session metadata enrichment --- .../web/src/lib/__tests__/serialize.test.ts | 35 +++++++++++++++++++ packages/web/src/lib/serialize.ts | 34 ++++++++++++++---- 2 files changed, 63 insertions(+), 6 deletions(-) diff --git a/packages/web/src/lib/__tests__/serialize.test.ts b/packages/web/src/lib/__tests__/serialize.test.ts index 02b4ea3b4..43f37d915 100644 --- a/packages/web/src/lib/__tests__/serialize.test.ts +++ b/packages/web/src/lib/__tests__/serialize.test.ts @@ -809,6 +809,41 @@ describe("enrichSessionsMetadata", () => { expect(dashboard.issueTitle).toBe("Fix auth bug"); }); + it("starts issue-title fetches before agent summaries finish", async () => { + let resolveSummary: ((value: { summary: string; summaryIsFallback: false; agentSessionId: string }) => void) | null = null; + + const tracker = mockTracker("Fix auth bug"); + const agent = { + ...mockAgent(), + getSessionInfo: vi.fn().mockImplementation( + () => new Promise((resolve) => { + resolveSummary = resolve; + }), + ), + } as Agent; + const registry = mockRegistry(tracker, agent); + + const core = createCoreSession({ issueId: `${urlBase}-parallel` }); + const dashboard = sessionToDashboard(core); + + const enrichmentPromise = enrichSessionsMetadata([core], [dashboard], testConfig, registry); + await Promise.resolve(); + + expect(tracker.getIssue).toHaveBeenCalledTimes(1); + expect(dashboard.issueLabel).toBe("#42"); + expect(dashboard.summary).toBeNull(); + + resolveSummary?.({ + summary: "Implementing auth fix", + summaryIsFallback: false, + agentSessionId: "abc", + }); + await enrichmentPromise; + + expect(dashboard.summary).toBe("Implementing auth fix"); + expect(dashboard.issueTitle).toBe("Fix auth bug"); + }); + it("should skip sessions without issue URLs", async () => { const tracker = mockTracker(); const agent = mockAgent(); diff --git a/packages/web/src/lib/serialize.ts b/packages/web/src/lib/serialize.ts index c30eabc57..0d61ee81f 100644 --- a/packages/web/src/lib/serialize.ts +++ b/packages/web/src/lib/serialize.ts @@ -372,6 +372,25 @@ export async function enrichSessionsMetadataFast( config: OrchestratorConfig, registry: PluginRegistry, ): Promise { + const { summaryPromises } = prepareSessionMetadataEnrichment( + coreSessions, + dashboardSessions, + config, + registry, + ); + + await Promise.allSettled(summaryPromises); +} + +function prepareSessionMetadataEnrichment( + coreSessions: Session[], + dashboardSessions: DashboardSession[], + config: OrchestratorConfig, + registry: PluginRegistry, +): { + projects: Array; + summaryPromises: Promise[]; +} { const projects = coreSessions.map((core) => resolveProject(core, config.projects)); // Issue labels (synchronous string parsing, no API calls) @@ -392,7 +411,7 @@ export async function enrichSessionsMetadataFast( return enrichSessionAgentSummary(dashboardSessions[i], core, agent); }); - await Promise.allSettled(summaryPromises); + return { projects, summaryPromises }; } /** @@ -405,11 +424,14 @@ export async function enrichSessionsMetadata( config: OrchestratorConfig, registry: PluginRegistry, ): Promise { - // Run fast enrichment first (labels + summaries) - await enrichSessionsMetadataFast(coreSessions, dashboardSessions, config, registry); + const { projects, summaryPromises } = prepareSessionMetadataEnrichment( + coreSessions, + dashboardSessions, + config, + registry, + ); - // Then add issue titles (tracker API, cached with TTL) - const projects = coreSessions.map((core) => resolveProject(core, config.projects)); + // Issue-title fetches depend on labels being set, but can run in parallel with summary I/O. const issueTitlePromises = projects.map((project, i) => { if (!dashboardSessions[i].issueUrl || !dashboardSessions[i].issueLabel) { return Promise.resolve(); @@ -420,7 +442,7 @@ export async function enrichSessionsMetadata( return enrichSessionIssueTitle(dashboardSessions[i], tracker, project); }); - await Promise.allSettled(issueTitlePromises); + await Promise.allSettled([...summaryPromises, ...issueTitlePromises]); } /** Compute dashboard stats from a list of sessions. */