Skip to content

Commit e526ff0

Browse files
committed
Fix
1 parent 0d6b485 commit e526ff0

File tree

3 files changed

+975
-17
lines changed

3 files changed

+975
-17
lines changed

apps/sim/executor/execution/executor.ts

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -124,42 +124,46 @@ export class DAGExecutor {
124124
throw new Error(validation.error)
125125
}
126126

127-
const { dirtySet, upstreamSet } = computeExecutionSets(dag, startBlockId)
127+
const { dirtySet, upstreamSet, reachableUpstreamSet } = computeExecutionSets(dag, startBlockId)
128128
const effectiveStartBlockId = resolveContainerToSentinelStart(startBlockId, dag) ?? startBlockId
129129

130-
// Extract container IDs from sentinel IDs in upstream set
131-
const upstreamContainerIds = new Set<string>()
132-
for (const nodeId of upstreamSet) {
130+
// Extract container IDs from sentinel IDs in reachable upstream set
131+
// Use reachableUpstreamSet (not upstreamSet) to preserve sibling branch outputs
132+
// Example: A->C, B->C where C references A.result || B.result
133+
// When running from A, B's output should be preserved for C to reference
134+
const reachableContainerIds = new Set<string>()
135+
for (const nodeId of reachableUpstreamSet) {
133136
const loopId = extractLoopIdFromSentinel(nodeId)
134-
if (loopId) upstreamContainerIds.add(loopId)
137+
if (loopId) reachableContainerIds.add(loopId)
135138
const parallelId = extractParallelIdFromSentinel(nodeId)
136-
if (parallelId) upstreamContainerIds.add(parallelId)
139+
if (parallelId) reachableContainerIds.add(parallelId)
137140
}
138141

139-
// Filter snapshot to only include upstream blocks - prevents references to non-upstream blocks
142+
// Filter snapshot to include all blocks reachable from dirty blocks
143+
// This preserves sibling branch outputs that dirty blocks may reference
140144
const filteredBlockStates: Record<string, any> = {}
141145
for (const [blockId, state] of Object.entries(sourceSnapshot.blockStates)) {
142-
if (upstreamSet.has(blockId) || upstreamContainerIds.has(blockId)) {
146+
if (reachableUpstreamSet.has(blockId) || reachableContainerIds.has(blockId)) {
143147
filteredBlockStates[blockId] = state
144148
}
145149
}
146150
const filteredExecutedBlocks = sourceSnapshot.executedBlocks.filter(
147-
(id) => upstreamSet.has(id) || upstreamContainerIds.has(id)
151+
(id) => reachableUpstreamSet.has(id) || reachableContainerIds.has(id)
148152
)
149153

150-
// Filter loop/parallel executions to only include upstream containers
154+
// Filter loop/parallel executions to only include reachable containers
151155
const filteredLoopExecutions: Record<string, any> = {}
152156
if (sourceSnapshot.loopExecutions) {
153157
for (const [loopId, execution] of Object.entries(sourceSnapshot.loopExecutions)) {
154-
if (upstreamContainerIds.has(loopId)) {
158+
if (reachableContainerIds.has(loopId)) {
155159
filteredLoopExecutions[loopId] = execution
156160
}
157161
}
158162
}
159163
const filteredParallelExecutions: Record<string, any> = {}
160164
if (sourceSnapshot.parallelExecutions) {
161165
for (const [parallelId, execution] of Object.entries(sourceSnapshot.parallelExecutions)) {
162-
if (upstreamContainerIds.has(parallelId)) {
166+
if (reachableContainerIds.has(parallelId)) {
163167
filteredParallelExecutions[parallelId] = execution
164168
}
165169
}
@@ -179,6 +183,7 @@ export class DAGExecutor {
179183
effectiveStartBlockId,
180184
dirtySetSize: dirtySet.size,
181185
upstreamSetSize: upstreamSet.size,
186+
reachableUpstreamSetSize: reachableUpstreamSet.size,
182187
})
183188

184189
// Remove incoming edges from non-dirty sources so convergent blocks don't wait for cached upstream

0 commit comments

Comments
 (0)