mirror of
https://github.com/paperclipai/paperclip.git
synced 2026-10-26 18:31:34 +01:00
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:
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);
|
||||
|
||||
|
||||
@@ -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?: {
|
||||
|
||||
Reference in new issue
Block a user