fix(workspaces): keep inventory reads DB-only

Backport the existing master guard so this long-lived feature worktree does not fan out Git scans across its cloned workspace inventory.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
DottaandPaperclip committed 2026-08-20 21:20:02 +00:00
1 parent b4b59388e5
commit 3d3a12a3e2
2 files changed
+26 -6

No files matched your search

@@ -3873,7 +3873,7 @@ describeEmbeddedPostgres("executionWorkspaceService.getCloseReadiness", () => {
expect(comments).toHaveLength(0);
}, 20_000);
it("returns full details at the observed volume without multiplying unconfigured shared service history", async () => {
it("keeps a large collection DB-only while a concurrent health-style query remains responsive", async () => {
const companyId = randomUUID();
const projectId = randomUUID();
const projectWorkspaceId = randomUUID();
@@ -3935,9 +3935,21 @@ describeEmbeddedPostgres("executionWorkspaceService.getCloseReadiness", () => {
})),
);
const workspaces = await svc.list(companyId);
const inspectGitCloseReadiness = vi.fn(async () => {
throw new Error("collection inventory must not inspect git worktrees");
});
const inventoryService = executionWorkspaceService(db, { inspectGitCloseReadiness });
const inventoryPromise = inventoryService.list(companyId);
const healthResponsive = await Promise.race([
db.execute(sql`select 1 as ok`).then(() => true),
new Promise<false>((resolve) => setTimeout(() => resolve(false), 2_000)),
]);
const workspaces = await inventoryPromise;
expect(healthResponsive).toBe(true);
expect(inspectGitCloseReadiness).not.toHaveBeenCalled();
expect(workspaces).toHaveLength(workspaceCount);
expect(workspaces.every((workspace) => workspace.deliveryState === "unknown")).toBe(true);
expect(workspaces.reduce((count, workspace) => count + (workspace.runtimeServices?.length ?? 0), 0)).toBe(0);
expect(JSON.stringify(workspaces).length).toBeLessThan(12_000_000);
+12 -4
View File
@@ -230,6 +230,10 @@ export type ExecutionWorkspaceServiceOptions = {
// becomes terminal before it archives the workspace. A value of 0 disables
// the cooldown. The default is 7 days.
workspaceReaperCooldownDays?: number;
inspectGitCloseReadiness?: (workspace: ExecutionWorkspace) => Promise<{
git: ExecutionWorkspaceCloseGitReadiness | null;
warnings: string[];
}>;
};
function parseGitHubRepository(repoUrl: string | null) {
@@ -1467,7 +1471,7 @@ export function executionWorkspaceService(db: Db, opts: ExecutionWorkspaceServic
async function hydrateWorkspace(row: ExecutionWorkspaceRow, runtimeServices: WorkspaceRuntimeService[] = []) {
const workspace = toExecutionWorkspace(row, runtimeServices);
const { git } = await inspectGitCloseReadiness(workspace);
const { git } = await (opts.inspectGitCloseReadiness ?? inspectGitCloseReadiness)(workspace);
const assessment = await assessDelivery(row, git);
return toExecutionWorkspace(row, runtimeServices, assessment.deliveryState);
}
@@ -2060,12 +2064,16 @@ export function executionWorkspaceService(db: Db, opts: ExecutionWorkspaceServic
.where(and(...conditions))
.orderBy(desc(executionWorkspaces.lastUsedAt), desc(executionWorkspaces.createdAt));
const runtimeServicesByWorkspaceId = await loadEffectiveRuntimeServicesByExecutionWorkspace(db, companyId, rows);
return Promise.all(rows.map((row) =>
hydrateWorkspace(
// Collection reads are deliberately DB-only. Delivery-state hydration
// inspects git and may resolve pull requests, so doing it for every row
// lets a large inventory launch an unbounded number of child processes.
// Detail and close-readiness reads retain the live hydration path.
return rows.map((row) =>
toExecutionWorkspace(
row,
(runtimeServicesByWorkspaceId.get(row.id) ?? []).map(toRuntimeService),
),
));
);
},
listSummaries: async (companyId: string, filters?: {