fix(core): Fix partial execution in triggerless parent case (#16833)

This commit is contained in:
Iván Ovejero
2025-06-30 15:20:15 +02:00
committed by GitHub
parent d76f05ba3d
commit 585295c89f
2 changed files with 61 additions and 2 deletions

View File

@@ -970,6 +970,47 @@ describe('WorkflowExecute', () => {
expect.objectContaining({ executionIndex: 1 }),
]);
});
// ►►
// ┌─────┐1 ┌─────┐
// │node1├──────►node2│
// └─────┘ └─────┘
test('should find closest parent with run data when no trigger exists', async () => {
// ARRANGE
const waitPromise = createDeferredPromise<IRun>();
const additionalData = Helpers.WorkflowExecuteAdditionalData(waitPromise);
const workflowExecute = new WorkflowExecute(additionalData, 'manual');
const node1 = createNodeData({ name: 'node1' });
const node2 = createNodeData({ name: 'node2' });
const workflow = new DirectedGraph()
.addNodes(node1, node2)
.addConnections({ from: node1, to: node2 })
.toWorkflow({ name: '', active: false, nodeTypes });
const pinData: IPinData = {};
const runData: IRunData = {
[node1.name]: [toITaskData([{ data: { name: node1.name } }])],
};
const dirtyNodeNames: string[] = [];
const destinationNode = node2.name;
const processRunExecutionDataSpy = jest
.spyOn(workflowExecute, 'processRunExecutionData')
.mockImplementationOnce(jest.fn());
// ACT
await workflowExecute.runPartialWorkflow2(
workflow,
runData,
pinData,
dirtyNodeNames,
destinationNode,
);
// ASSERT
expect(processRunExecutionDataSpy).toHaveBeenCalledTimes(1);
});
});
describe('checkReadyForExecution', () => {

View File

@@ -424,9 +424,27 @@ export class WorkflowExecute {
}
// 1. Find the Trigger
const trigger = findTriggerForPartialExecution(workflow, destinationNodeName, runData);
let trigger = findTriggerForPartialExecution(workflow, destinationNodeName, runData);
if (trigger === undefined) {
throw new UserError('Connect a trigger to run this node');
// destination has parents but none of them are triggers, so find the closest
// parent node that has run data, and treat that parent as starting point
let startNode;
const parentNodes = workflow.getParentNodes(destinationNodeName);
for (const nodeName of parentNodes) {
if (runData[nodeName]) {
startNode = workflow.getNode(nodeName);
break;
}
}
if (!startNode) {
throw new UserError('Connect a trigger to run this node');
}
trigger = startNode;
}
// 2. Find the Subgraph