mirror of
https://github.com/simstudioai/sim.git
synced 2026-02-15 17:05:14 -05:00
fix(condition): fixed deactivated edges when if and else if conditions connected to same destination block, added 100+ unit tests (#2497)
This commit is contained in:
1052
apps/sim/executor/execution/edge-manager.test.ts
Normal file
1052
apps/sim/executor/execution/edge-manager.test.ts
Normal file
File diff suppressed because it is too large
Load Diff
@@ -18,7 +18,10 @@ export class EdgeManager {
|
||||
): string[] {
|
||||
const readyNodes: string[] = []
|
||||
const activatedTargets: string[] = []
|
||||
const edgesToDeactivate: Array<{ target: string; handle?: string }> = []
|
||||
|
||||
// First pass: categorize edges as activating or deactivating
|
||||
// Don't modify incomingEdges yet - we need the original state for deactivation checks
|
||||
for (const [edgeId, edge] of node.outgoingEdges) {
|
||||
if (skipBackwardsEdge && this.isBackwardsEdge(edge.sourceHandle)) {
|
||||
continue
|
||||
@@ -32,23 +35,31 @@ export class EdgeManager {
|
||||
edge.sourceHandle === EDGE.LOOP_EXIT
|
||||
|
||||
if (!isLoopEdge) {
|
||||
this.deactivateEdgeAndDescendants(node.id, edge.target, edge.sourceHandle)
|
||||
edgesToDeactivate.push({ target: edge.target, handle: edge.sourceHandle })
|
||||
}
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
const targetNode = this.dag.nodes.get(edge.target)
|
||||
if (!targetNode) {
|
||||
logger.warn('Target node not found', { target: edge.target })
|
||||
continue
|
||||
}
|
||||
|
||||
targetNode.incomingEdges.delete(node.id)
|
||||
activatedTargets.push(edge.target)
|
||||
}
|
||||
|
||||
// Check readiness after all edges processed to ensure cascade deactivations are complete
|
||||
// Second pass: process deactivations while incomingEdges is still intact
|
||||
// This ensures hasActiveIncomingEdges can find all potential sources
|
||||
for (const { target, handle } of edgesToDeactivate) {
|
||||
this.deactivateEdgeAndDescendants(node.id, target, handle)
|
||||
}
|
||||
|
||||
// Third pass: update incomingEdges for activated targets
|
||||
for (const targetId of activatedTargets) {
|
||||
const targetNode = this.dag.nodes.get(targetId)
|
||||
if (!targetNode) {
|
||||
logger.warn('Target node not found', { target: targetId })
|
||||
continue
|
||||
}
|
||||
targetNode.incomingEdges.delete(node.id)
|
||||
}
|
||||
|
||||
// Fourth pass: check readiness after all edge processing is complete
|
||||
for (const targetId of activatedTargets) {
|
||||
const targetNode = this.dag.nodes.get(targetId)
|
||||
if (targetNode && this.isNodeReady(targetNode)) {
|
||||
@@ -162,7 +173,10 @@ export class EdgeManager {
|
||||
const targetNode = this.dag.nodes.get(targetId)
|
||||
if (!targetNode) return
|
||||
|
||||
const hasOtherActiveIncoming = this.hasActiveIncomingEdges(targetNode, sourceId)
|
||||
// Check if target has other active incoming edges
|
||||
// Pass the specific edge key being deactivated, not just source ID,
|
||||
// to handle multiple edges from same source to same target (e.g., condition branches)
|
||||
const hasOtherActiveIncoming = this.hasActiveIncomingEdges(targetNode, edgeKey)
|
||||
if (!hasOtherActiveIncoming) {
|
||||
for (const [_, outgoingEdge] of targetNode.outgoingEdges) {
|
||||
this.deactivateEdgeAndDescendants(targetId, outgoingEdge.target, outgoingEdge.sourceHandle)
|
||||
@@ -170,10 +184,13 @@ export class EdgeManager {
|
||||
}
|
||||
}
|
||||
|
||||
private hasActiveIncomingEdges(node: DAGNode, excludeSourceId: string): boolean {
|
||||
/**
|
||||
* Checks if a node has any active incoming edges besides the one being excluded.
|
||||
* This properly handles the case where multiple edges from the same source go to
|
||||
* the same target (e.g., multiple condition branches pointing to one block).
|
||||
*/
|
||||
private hasActiveIncomingEdges(node: DAGNode, excludeEdgeKey: string): boolean {
|
||||
for (const incomingSourceId of node.incomingEdges) {
|
||||
if (incomingSourceId === excludeSourceId) continue
|
||||
|
||||
const incomingNode = this.dag.nodes.get(incomingSourceId)
|
||||
if (!incomingNode) continue
|
||||
|
||||
@@ -184,6 +201,8 @@ export class EdgeManager {
|
||||
node.id,
|
||||
incomingEdge.sourceHandle
|
||||
)
|
||||
// Skip the specific edge being excluded, but check other edges from same source
|
||||
if (incomingEdgeKey === excludeEdgeKey) continue
|
||||
if (!this.deactivatedEdges.has(incomingEdgeKey)) {
|
||||
return true
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user