mirror of
https://github.com/n8n-io/n8n.git
synced 2024-09-20 06:47:32 -07:00
🐛 Execute node also if it is a sibling but does not receive data
from parent
This commit is contained in:
parent
caad6d1c8d
commit
c811294612
|
@ -22,6 +22,8 @@ import {
|
||||||
NodeExecuteFunctions,
|
NodeExecuteFunctions,
|
||||||
} from './';
|
} from './';
|
||||||
|
|
||||||
|
import { get } from 'lodash';
|
||||||
|
|
||||||
export class WorkflowExecute {
|
export class WorkflowExecute {
|
||||||
runExecutionData: IRunExecutionData;
|
runExecutionData: IRunExecutionData;
|
||||||
private additionalData: IWorkflowExecuteAdditionalData;
|
private additionalData: IWorkflowExecuteAdditionalData;
|
||||||
|
@ -234,6 +236,21 @@ export class WorkflowExecute {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks the incoming connection does not receive any data
|
||||||
|
*/
|
||||||
|
incomingConnectionIsEmpty(runData: IRunData, inputConnections: IConnection[], runIndex: number): boolean {
|
||||||
|
// for (const inputConnection of workflow.connectionsByDestinationNode[nodeToAdd].main[0]) {
|
||||||
|
for (const inputConnection of inputConnections) {
|
||||||
|
const nodeIncomingData = get(runData, `[${inputConnection.node}][${runIndex}].data.main[${inputConnection.index}]`);
|
||||||
|
if (nodeIncomingData !== undefined && (nodeIncomingData as object[]).length !== 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
addNodeToBeExecuted(workflow: Workflow, connectionData: IConnection, outputIndex: number, parentNodeName: string, nodeSuccessData: INodeExecutionData[][], runIndex: number): void {
|
addNodeToBeExecuted(workflow: Workflow, connectionData: IConnection, outputIndex: number, parentNodeName: string, nodeSuccessData: INodeExecutionData[][], runIndex: number): void {
|
||||||
let stillDataMissing = false;
|
let stillDataMissing = false;
|
||||||
|
|
||||||
|
@ -299,7 +316,7 @@ export class WorkflowExecute {
|
||||||
|
|
||||||
if (nodeWasWaiting === false) {
|
if (nodeWasWaiting === false) {
|
||||||
|
|
||||||
// Get a list of all the output nodes that we can check for siblings eaiser
|
// Get a list of all the output nodes that we can check for siblings easier
|
||||||
const checkOutputNodes = [];
|
const checkOutputNodes = [];
|
||||||
for (const outputIndexParent in workflow.connectionsBySourceNode[parentNodeName].main) {
|
for (const outputIndexParent in workflow.connectionsBySourceNode[parentNodeName].main) {
|
||||||
if (!workflow.connectionsBySourceNode[parentNodeName].main.hasOwnProperty(outputIndexParent)) {
|
if (!workflow.connectionsBySourceNode[parentNodeName].main.hasOwnProperty(outputIndexParent)) {
|
||||||
|
@ -327,8 +344,12 @@ export class WorkflowExecute {
|
||||||
// previously processed one
|
// previously processed one
|
||||||
if (inputData.node !== parentNodeName && checkOutputNodes.includes(inputData.node)) {
|
if (inputData.node !== parentNodeName && checkOutputNodes.includes(inputData.node)) {
|
||||||
// So the parent node will be added anyway which
|
// So the parent node will be added anyway which
|
||||||
// will then process this node next. So nothing to do.
|
// will then process this node next. So nothing to do
|
||||||
continue;
|
// unless the incoming data of the node is empty
|
||||||
|
// because then it would not be executed
|
||||||
|
if (!this.incomingConnectionIsEmpty(this.runExecutionData.resultData.runData, workflow.connectionsByDestinationNode[inputData.node].main[0], runIndex)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if it is already in the execution stack
|
// Check if it is already in the execution stack
|
||||||
|
@ -384,7 +405,19 @@ export class WorkflowExecute {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (workflow.connectionsByDestinationNode[nodeToAdd] === undefined) {
|
let addEmptyItem = false;
|
||||||
|
|
||||||
|
if (workflow.connectionsByDestinationNode[nodeToAdd] === undefined) {
|
||||||
|
// Add empty item if the node does not have any input connections
|
||||||
|
addEmptyItem = true;
|
||||||
|
} else {
|
||||||
|
if (this.incomingConnectionIsEmpty(this.runExecutionData.resultData.runData, workflow.connectionsByDestinationNode[nodeToAdd].main[0], runIndex)) {
|
||||||
|
// Add empty item also if the input data is empty
|
||||||
|
addEmptyItem = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (addEmptyItem === true) {
|
||||||
// Add only node if it does not have any inputs because else it will
|
// Add only node if it does not have any inputs because else it will
|
||||||
// be added by its input node later anyway.
|
// be added by its input node later anyway.
|
||||||
this.runExecutionData.executionData!.nodeExecutionStack.push(
|
this.runExecutionData.executionData!.nodeExecutionStack.push(
|
||||||
|
|
|
@ -986,6 +986,172 @@ describe('WorkflowExecute', () => {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
description: 'should use empty data if input of sibling does not receive any data from parent',
|
||||||
|
input: {
|
||||||
|
// Leave the workflowData in regular JSON to be able to easily
|
||||||
|
// copy it from/in the UI
|
||||||
|
workflowData: {
|
||||||
|
"nodes": [
|
||||||
|
{
|
||||||
|
"parameters": {},
|
||||||
|
"name": "Start",
|
||||||
|
"type": "n8n-nodes-base.start",
|
||||||
|
"typeVersion": 1,
|
||||||
|
"position": [
|
||||||
|
250,
|
||||||
|
300,
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"parameters": {
|
||||||
|
"conditions": {
|
||||||
|
"number": [
|
||||||
|
{
|
||||||
|
"value1": "={{$json[\"value1\"]}}",
|
||||||
|
"operation": "equal",
|
||||||
|
"value2": 1,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"name": "IF",
|
||||||
|
"type": "n8n-nodes-base.if",
|
||||||
|
"typeVersion": 1,
|
||||||
|
"position": [
|
||||||
|
650,
|
||||||
|
300,
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"parameters": {
|
||||||
|
"values": {
|
||||||
|
"string": [],
|
||||||
|
"number": [
|
||||||
|
{
|
||||||
|
"name": "value2",
|
||||||
|
"value": 2,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
"options": {},
|
||||||
|
},
|
||||||
|
"name": "Set2",
|
||||||
|
"type": "n8n-nodes-base.set",
|
||||||
|
"typeVersion": 1,
|
||||||
|
"position": [
|
||||||
|
850,
|
||||||
|
450,
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"parameters": {
|
||||||
|
"values": {
|
||||||
|
"number": [
|
||||||
|
{
|
||||||
|
"name": "value1",
|
||||||
|
"value": 1,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
"options": {},
|
||||||
|
},
|
||||||
|
"name": "Set1",
|
||||||
|
"type": "n8n-nodes-base.set",
|
||||||
|
"typeVersion": 1,
|
||||||
|
"position": [
|
||||||
|
450,
|
||||||
|
300,
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"parameters": {},
|
||||||
|
"name": "Merge",
|
||||||
|
"type": "n8n-nodes-base.merge",
|
||||||
|
"typeVersion": 1,
|
||||||
|
"position": [
|
||||||
|
1050,
|
||||||
|
300,
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"connections": {
|
||||||
|
"Start": {
|
||||||
|
"main": [
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"node": "Set1",
|
||||||
|
"type": "main",
|
||||||
|
"index": 0,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
],
|
||||||
|
},
|
||||||
|
"IF": {
|
||||||
|
"main": [
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"node": "Merge",
|
||||||
|
"type": "main",
|
||||||
|
"index": 0,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"node": "Set2",
|
||||||
|
"type": "main",
|
||||||
|
"index": 0,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
],
|
||||||
|
},
|
||||||
|
"Set2": {
|
||||||
|
"main": [
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"node": "Merge",
|
||||||
|
"type": "main",
|
||||||
|
"index": 1,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
],
|
||||||
|
},
|
||||||
|
"Set1": {
|
||||||
|
"main": [
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"node": "IF",
|
||||||
|
"type": "main",
|
||||||
|
"index": 0,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
output: {
|
||||||
|
nodeExecutionOrder: [
|
||||||
|
'Start',
|
||||||
|
'Set1',
|
||||||
|
'IF',
|
||||||
|
'Set2',
|
||||||
|
'Merge',
|
||||||
|
],
|
||||||
|
nodeData: {
|
||||||
|
Merge: [
|
||||||
|
[
|
||||||
|
{
|
||||||
|
value1: 1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value2: 2,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue