Skip to content

Commit 69300db

Browse files
committed
deal with unbounded memory possibility
1 parent f2ec83d commit 69300db

1 file changed

Lines changed: 19 additions & 0 deletions

File tree

apps/sim/lib/workspaces/fork/copy/deploy-bridge.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,22 @@ import { createLogger } from '@sim/logger'
44
import { and, eq, isNull } from 'drizzle-orm'
55
import type { DbOrTx } from '@/lib/db/types'
66
import { loadDeployedWorkflowState } from '@/lib/workflows/persistence/utils'
7+
import { ForkError } from '@/lib/workspaces/fork/lineage/authz'
78
import type { Variable, WorkflowState } from '@/stores/workflows/workflow/types'
89

910
const logger = createLogger('WorkspaceForkDeployBridge')
1011

12+
/**
13+
* Hard ceiling on how many deployed workflows one fork/promote loads into memory at
14+
* once (each as a full `WorkflowState`). There is no per-workspace workflow cap in
15+
* the product, so this is the safety valve: real workspaces hold tens to low
16+
* hundreds, making this ~5-10x headroom that never blocks legitimate use, it sits
17+
* below the fork feature's other item caps (resource selection 2000, mapping
18+
* entries 5000 - both lighter-weight than full states), and it bounds a pathological
19+
* workspace to a few hundred MB of transient state instead of an unbounded load.
20+
*/
21+
export const MAX_FORK_DEPLOYED_WORKFLOWS = 1000
22+
1123
export interface DeployedWorkflowSummary {
1224
id: string
1325
name: string
@@ -74,6 +86,13 @@ export async function loadSourceDeployedStates(sourceWorkspaceId: string): Promi
7486
sourceStates: Map<string, WorkflowState>
7587
}> {
7688
const deployedWorkflows = await listDeployedWorkflows(db, sourceWorkspaceId)
89+
// Fail fast on the cheap count before loading any heavy state into memory.
90+
if (deployedWorkflows.length > MAX_FORK_DEPLOYED_WORKFLOWS) {
91+
throw new ForkError(
92+
`This workspace has ${deployedWorkflows.length} deployed workflows, which exceeds the fork/sync limit of ${MAX_FORK_DEPLOYED_WORKFLOWS}.`,
93+
400
94+
)
95+
}
7796
const sourceStates = new Map<string, WorkflowState>()
7897
for (const wf of deployedWorkflows) {
7998
const state = await readDeployedState(wf.id, sourceWorkspaceId)

0 commit comments

Comments
 (0)