From cbb98a08686168fe33d2f78b46d2e5734a4f63fb Mon Sep 17 00:00:00 2001 From: waleed Date: Sat, 14 Feb 2026 12:58:18 -0800 Subject: [PATCH] fix(executor): resolve block ID for parallel subflow active state --- .../hooks/use-workflow-execution.ts | 19 +++++++++++++- .../utils/workflow-execution-utils.ts | 25 ++++++++++++++++--- apps/sim/executor/execution/block-executor.ts | 4 +-- 3 files changed, 41 insertions(+), 7 deletions(-) diff --git a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/hooks/use-workflow-execution.ts b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/hooks/use-workflow-execution.ts index 1088f8c87..fceade9a1 100644 --- a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/hooks/use-workflow-execution.ts +++ b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/hooks/use-workflow-execution.ts @@ -63,6 +63,7 @@ interface BlockEventHandlerConfig { executionIdRef: { current: string } workflowEdges: Array<{ id: string; target: string; sourceHandle?: string | null }> activeBlocksSet: Set + activeBlockRefCounts: Map accumulatedBlockLogs: BlockLog[] accumulatedBlockStates: Map executedBlockIds: Set @@ -309,6 +310,7 @@ export function useWorkflowExecution() { executionIdRef, workflowEdges, activeBlocksSet, + activeBlockRefCounts, accumulatedBlockLogs, accumulatedBlockStates, executedBlockIds, @@ -328,9 +330,18 @@ export function useWorkflowExecution() { const updateActiveBlocks = (blockId: string, isActive: boolean) => { if (!workflowId) return if (isActive) { + const count = activeBlockRefCounts.get(blockId) ?? 0 + activeBlockRefCounts.set(blockId, count + 1) activeBlocksSet.add(blockId) } else { - activeBlocksSet.delete(blockId) + const count = activeBlockRefCounts.get(blockId) ?? 1 + const next = count - 1 + if (next <= 0) { + activeBlockRefCounts.delete(blockId) + activeBlocksSet.delete(blockId) + } else { + activeBlockRefCounts.set(blockId, next) + } } setActiveBlocks(workflowId, new Set(activeBlocksSet)) } @@ -1280,6 +1291,7 @@ export function useWorkflowExecution() { } const activeBlocksSet = new Set() + const activeBlockRefCounts = new Map() const streamedContent = new Map() const accumulatedBlockLogs: BlockLog[] = [] const accumulatedBlockStates = new Map() @@ -1292,6 +1304,7 @@ export function useWorkflowExecution() { executionIdRef, workflowEdges, activeBlocksSet, + activeBlockRefCounts, accumulatedBlockLogs, accumulatedBlockStates, executedBlockIds, @@ -1902,6 +1915,7 @@ export function useWorkflowExecution() { const accumulatedBlockStates = new Map() const executedBlockIds = new Set() const activeBlocksSet = new Set() + const activeBlockRefCounts = new Map() try { const blockHandlers = buildBlockEventHandlers({ @@ -1909,6 +1923,7 @@ export function useWorkflowExecution() { executionIdRef, workflowEdges, activeBlocksSet, + activeBlockRefCounts, accumulatedBlockLogs, accumulatedBlockStates, executedBlockIds, @@ -2104,6 +2119,7 @@ export function useWorkflowExecution() { const workflowEdges = useWorkflowStore.getState().edges const activeBlocksSet = new Set() + const activeBlockRefCounts = new Map() const accumulatedBlockLogs: BlockLog[] = [] const accumulatedBlockStates = new Map() const executedBlockIds = new Set() @@ -2115,6 +2131,7 @@ export function useWorkflowExecution() { executionIdRef, workflowEdges, activeBlocksSet, + activeBlockRefCounts, accumulatedBlockLogs, accumulatedBlockStates, executedBlockIds, diff --git a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/utils/workflow-execution-utils.ts b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/utils/workflow-execution-utils.ts index c0e54ea43..bf5e2e531 100644 --- a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/utils/workflow-execution-utils.ts +++ b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/utils/workflow-execution-utils.ts @@ -39,6 +39,7 @@ export async function executeWorkflowWithFullLogging( const workflowEdges = useWorkflowStore.getState().edges const activeBlocksSet = new Set() + const activeBlockRefCounts = new Map() const payload: any = { input: options.workflowInput, @@ -103,6 +104,8 @@ export async function executeWorkflowWithFullLogging( switch (event.type) { case 'block:started': { + const startCount = activeBlockRefCounts.get(event.data.blockId) ?? 0 + activeBlockRefCounts.set(event.data.blockId, startCount + 1) activeBlocksSet.add(event.data.blockId) setActiveBlocks(wfId, new Set(activeBlocksSet)) @@ -115,8 +118,14 @@ export async function executeWorkflowWithFullLogging( break } - case 'block:completed': - activeBlocksSet.delete(event.data.blockId) + case 'block:completed': { + const completeCount = activeBlockRefCounts.get(event.data.blockId) ?? 1 + if (completeCount <= 1) { + activeBlockRefCounts.delete(event.data.blockId) + activeBlocksSet.delete(event.data.blockId) + } else { + activeBlockRefCounts.set(event.data.blockId, completeCount - 1) + } setActiveBlocks(wfId, new Set(activeBlocksSet)) setBlockRunStatus(wfId, event.data.blockId, 'success') @@ -144,9 +153,16 @@ export async function executeWorkflowWithFullLogging( options.onBlockComplete(event.data.blockId, event.data.output).catch(() => {}) } break + } - case 'block:error': - activeBlocksSet.delete(event.data.blockId) + case 'block:error': { + const errorCount = activeBlockRefCounts.get(event.data.blockId) ?? 1 + if (errorCount <= 1) { + activeBlockRefCounts.delete(event.data.blockId) + activeBlocksSet.delete(event.data.blockId) + } else { + activeBlockRefCounts.set(event.data.blockId, errorCount - 1) + } setActiveBlocks(wfId, new Set(activeBlocksSet)) setBlockRunStatus(wfId, event.data.blockId, 'error') @@ -171,6 +187,7 @@ export async function executeWorkflowWithFullLogging( iterationContainerId: event.data.iterationContainerId, }) break + } case 'execution:completed': executionResult = { diff --git a/apps/sim/executor/execution/block-executor.ts b/apps/sim/executor/execution/block-executor.ts index 58143e583..56b7c6a91 100644 --- a/apps/sim/executor/execution/block-executor.ts +++ b/apps/sim/executor/execution/block-executor.ts @@ -428,7 +428,7 @@ export class BlockExecutor { block: SerializedBlock, executionOrder: number ): void { - const blockId = node.id + const blockId = node.metadata?.originalBlockId ?? node.id const blockName = block.metadata?.name ?? blockId const blockType = block.metadata?.id ?? DEFAULTS.BLOCK_TYPE @@ -456,7 +456,7 @@ export class BlockExecutor { executionOrder: number, endedAt: string ): void { - const blockId = node.id + const blockId = node.metadata?.originalBlockId ?? node.id const blockName = block.metadata?.name ?? blockId const blockType = block.metadata?.id ?? DEFAULTS.BLOCK_TYPE