fix: Load workflows with unconnected Switch outputs (#12020)

This commit is contained in:
Mutasem Aldmour
2024-12-04 13:44:25 +01:00
committed by GitHub
parent bd693162b8
commit abc851c0cf
24 changed files with 324 additions and 89 deletions

View File

@@ -448,7 +448,7 @@ export class DirectedGraph {
for (const [outputType, outputs] of Object.entries(iConnection)) {
for (const [outputIndex, conns] of outputs.entries()) {
for (const conn of conns) {
for (const conn of conns ?? []) {
// TODO: What's with the input type?
const { node: toNodeName, type: _inputType, index: inputIndex } = conn;
const to = workflow.getNode(toNodeName);

View File

@@ -42,6 +42,28 @@ describe('DirectedGraph', () => {
);
});
// ┌─────┐ ┌─────┐──► null
// │node1├───►│node2| ┌─────┐
// └─────┘ └─────┘──►│node3|
// └─────┘
//
test('linear workflow with null connections', () => {
// ARRANGE
const node1 = createNodeData({ name: 'Node1' });
const node2 = createNodeData({ name: 'Node2' });
const node3 = createNodeData({ name: 'Node3' });
// ACT
const graph = new DirectedGraph()
.addNodes(node1, node2, node3)
.addConnections({ from: node1, to: node2 }, { from: node2, to: node3, outputIndex: 1 });
// ASSERT
expect(DirectedGraph.fromWorkflow(graph.toWorkflow({ ...defaultWorkflowParameter }))).toEqual(
graph,
);
});
describe('getChildren', () => {
// ┌─────┐ ┌─────┐ ┌─────┐
// │node1├───►│node2├──►│node3│

View File

@@ -36,6 +36,7 @@ import type {
CloseFunction,
StartNodeData,
NodeExecutionHint,
NodeInputConnections,
} from 'n8n-workflow';
import {
LoggerProxy as Logger,
@@ -208,6 +209,9 @@ export class WorkflowExecute {
// Get the data of the incoming connections
incomingSourceData = { main: [] };
for (const connections of incomingNodeConnections.main) {
if (!connections) {
continue;
}
for (let inputIndex = 0; inputIndex < connections.length; inputIndex++) {
connection = connections[inputIndex];
@@ -249,6 +253,9 @@ export class WorkflowExecute {
incomingNodeConnections = workflow.connectionsByDestinationNode[destinationNode];
if (incomingNodeConnections !== undefined) {
for (const connections of incomingNodeConnections.main) {
if (!connections) {
continue;
}
for (let inputIndex = 0; inputIndex < connections.length; inputIndex++) {
connection = connections[inputIndex];
@@ -642,7 +649,7 @@ export class WorkflowExecute {
}
for (const connectionDataCheck of workflow.connectionsBySourceNode[parentNodeName].main[
outputIndexParent
]) {
] ?? []) {
checkOutputNodes.push(connectionDataCheck.node);
}
}
@@ -661,7 +668,7 @@ export class WorkflowExecute {
) {
for (const inputData of workflow.connectionsByDestinationNode[connectionData.node].main[
inputIndex
]) {
] ?? []) {
if (inputData.node === parentNodeName) {
// Is the node we come from so its data will be available for sure
continue;
@@ -681,7 +688,7 @@ export class WorkflowExecute {
if (
!this.incomingConnectionIsEmpty(
this.runExecutionData.resultData.runData,
workflow.connectionsByDestinationNode[inputData.node].main[0],
workflow.connectionsByDestinationNode[inputData.node].main[0] ?? [],
runIndex,
)
) {
@@ -770,7 +777,7 @@ export class WorkflowExecute {
} else if (
this.incomingConnectionIsEmpty(
this.runExecutionData.resultData.runData,
workflow.connectionsByDestinationNode[nodeToAdd].main[0],
workflow.connectionsByDestinationNode[nodeToAdd].main[0] ?? [],
runIndex,
)
) {
@@ -1066,7 +1073,7 @@ export class WorkflowExecute {
if (workflow.connectionsByDestinationNode.hasOwnProperty(executionNode.name)) {
// Check if the node has incoming connections
if (workflow.connectionsByDestinationNode[executionNode.name].hasOwnProperty('main')) {
let inputConnections: IConnection[][];
let inputConnections: NodeInputConnections;
let connectionIndex: number;
// eslint-disable-next-line prefer-const
@@ -1586,7 +1593,7 @@ export class WorkflowExecute {
// Iterate over all the different connections of this output
for (connectionData of workflow.connectionsBySourceNode[executionNode.name].main[
outputIndex
]) {
] ?? []) {
if (!workflow.nodes.hasOwnProperty(connectionData.node)) {
throw new ApplicationError('Destination node not found', {
extra: {