mirror of
https://github.com/Abdulazizzn/n8n-enterprise-unlocked.git
synced 2025-12-18 02:21:13 +00:00
fix(core): Use destination node to select the correct pinned trigger to start from (#15633)
Co-authored-by: Danny Martini <danny@n8n.io>
This commit is contained in:
@@ -1,6 +1,13 @@
|
||||
import type { User } from '@n8n/db';
|
||||
import { mock } from 'jest-mock-extended';
|
||||
import type { INode, IWorkflowBase, INodeType, IWorkflowExecuteAdditionalData } from 'n8n-workflow';
|
||||
import {
|
||||
NodeConnectionTypes,
|
||||
type IConnections,
|
||||
type INode,
|
||||
type INodeType,
|
||||
type IWorkflowBase,
|
||||
type IWorkflowExecuteAdditionalData,
|
||||
} from 'n8n-workflow';
|
||||
|
||||
import type { NodeTypes } from '@/node-types';
|
||||
import * as WorkflowExecuteAdditionalData from '@/workflow-execute-additional-data';
|
||||
@@ -52,6 +59,15 @@ const hackerNewsNode: INode = {
|
||||
position: [0, 0],
|
||||
};
|
||||
|
||||
const secondHackerNewsNode: INode = {
|
||||
name: 'Hacker News 2',
|
||||
type: 'n8n-nodes-base.hackerNews',
|
||||
id: '55d63bca-bb6c-4568-948f-8ed9aacb1fe3',
|
||||
parameters: {},
|
||||
typeVersion: 1,
|
||||
position: [0, 0],
|
||||
};
|
||||
|
||||
describe('WorkflowExecutionService', () => {
|
||||
const nodeTypes = mock<NodeTypes>();
|
||||
const workflowRunner = mock<WorkflowRunner>();
|
||||
@@ -417,6 +433,23 @@ describe('WorkflowExecutionService', () => {
|
||||
expect(node).toEqual(webhookNode);
|
||||
});
|
||||
|
||||
it('should favor webhook node connected to the destination node', () => {
|
||||
workflow.nodes.push(webhookNode, secondWebhookNode, hackerNewsNode, secondHackerNewsNode);
|
||||
workflow.connections = {
|
||||
...createMainConnection(webhookNode.name, hackerNewsNode.name),
|
||||
...createMainConnection(secondWebhookNode.name, secondHackerNewsNode.name),
|
||||
};
|
||||
|
||||
const node = workflowExecutionService.selectPinnedActivatorStarter(
|
||||
workflow,
|
||||
[],
|
||||
{ ...pinData, [secondWebhookNode.name]: [{ json: { key: 'value' } }] },
|
||||
secondHackerNewsNode.name,
|
||||
);
|
||||
|
||||
expect(node).toEqual(secondWebhookNode);
|
||||
});
|
||||
|
||||
describe('offloading manual executions to workers', () => {
|
||||
test('when receiving no `runData`, should set `runData` to undefined in `executionData`', async () => {
|
||||
const originalEnv = process.env;
|
||||
@@ -458,3 +491,19 @@ describe('WorkflowExecutionService', () => {
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
function createMainConnection(targetNode: string, sourceNode: string): IConnections {
|
||||
return {
|
||||
[sourceNode]: {
|
||||
[NodeConnectionTypes.Main]: [
|
||||
[
|
||||
{
|
||||
node: targetNode,
|
||||
type: 'main',
|
||||
index: 0,
|
||||
},
|
||||
],
|
||||
],
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
@@ -117,6 +117,7 @@ export class WorkflowExecutionService {
|
||||
workflowData,
|
||||
startNodes?.map((nodeData) => nodeData.name),
|
||||
pinData,
|
||||
destinationNode,
|
||||
);
|
||||
|
||||
// TODO: Reverse the order of events, first find out if the execution is
|
||||
@@ -378,7 +379,12 @@ export class WorkflowExecutionService {
|
||||
* prioritizing `n8n-nodes-base.webhook` over other activators. If the executed node
|
||||
* has no upstream nodes and is itself is a pinned activator, select it.
|
||||
*/
|
||||
selectPinnedActivatorStarter(workflow: IWorkflowBase, startNodes?: string[], pinData?: IPinData) {
|
||||
selectPinnedActivatorStarter(
|
||||
workflow: IWorkflowBase,
|
||||
startNodes?: string[],
|
||||
pinData?: IPinData,
|
||||
destinationNode?: string,
|
||||
) {
|
||||
if (!pinData || !startNodes) return null;
|
||||
|
||||
const allPinnedActivators = this.findAllPinnedActivators(workflow, pinData);
|
||||
@@ -389,7 +395,27 @@ export class WorkflowExecutionService {
|
||||
|
||||
// full manual execution
|
||||
|
||||
if (startNodes?.length === 0) return firstPinnedActivator ?? null;
|
||||
if (startNodes?.length === 0) {
|
||||
// If there is a destination node, find the pinned activator that is a parent of the destination node
|
||||
if (destinationNode) {
|
||||
const destinationParents = new Set(
|
||||
new Workflow({
|
||||
nodes: workflow.nodes,
|
||||
connections: workflow.connections,
|
||||
active: workflow.active,
|
||||
nodeTypes: this.nodeTypes,
|
||||
}).getParentNodes(destinationNode),
|
||||
);
|
||||
|
||||
const activator = allPinnedActivators.find((a) => destinationParents.has(a.name));
|
||||
|
||||
if (activator) {
|
||||
return activator;
|
||||
}
|
||||
}
|
||||
|
||||
return firstPinnedActivator ?? null;
|
||||
}
|
||||
|
||||
// partial manual execution
|
||||
|
||||
|
||||
Reference in New Issue
Block a user