feat: Implement new partial execution logic for acyclic workflows (no-changelog) (#10256)

Co-authored-by: Tomi Turtiainen <10324676+tomi@users.noreply.github.com>
This commit is contained in:
Danny Martini
2024-09-18 15:06:36 +02:00
committed by GitHub
parent 73f89ef101
commit 2a084f96f8
31 changed files with 2367 additions and 20 deletions

View File

@@ -640,4 +640,13 @@ export const schema = {
env: 'N8N_PROXY_HOPS',
doc: 'Number of reverse-proxies n8n is running behind',
},
featureFlags: {
partialExecutionVersionDefault: {
format: String,
default: '0',
env: 'PARTIAL_EXECUTION_VERSION_DEFAULT',
doc: 'Set this to 1 to enable the new partial execution logic by default.',
},
},
};

View File

@@ -109,7 +109,9 @@ export class WorkflowRunner {
}
}
/** Run the workflow */
/** Run the workflow
* @param realtime This is used in queue mode to change the priority of an execution, making sure they are picked up quicker.
*/
async run(
data: IWorkflowExecutionDataProcess,
loadStaticData?: boolean,
@@ -278,6 +280,7 @@ export class WorkflowRunner {
data.startNodes === undefined ||
data.startNodes.length === 0
) {
// Full Execution
this.logger.debug(`Execution ID ${executionId} will run executing all nodes.`, {
executionId,
});
@@ -294,16 +297,27 @@ export class WorkflowRunner {
data.pinData,
);
} else {
// Partial Execution
this.logger.debug(`Execution ID ${executionId} is a partial execution.`, { executionId });
// Execute only the nodes between start and destination nodes
const workflowExecute = new WorkflowExecute(additionalData, data.executionMode);
workflowExecution = workflowExecute.runPartialWorkflow(
workflow,
data.runData,
data.startNodes,
data.destinationNode,
data.pinData,
);
if (data.partialExecutionVersion === '1') {
workflowExecution = workflowExecute.runPartialWorkflow2(
workflow,
data.runData,
data.destinationNode,
data.pinData,
);
} else {
workflowExecution = workflowExecute.runPartialWorkflow(
workflow,
data.runData,
data.startNodes,
data.destinationNode,
data.pinData,
);
}
}
this.activeExecutions.attachWorkflowExecution(executionId, workflowExecution);

View File

@@ -92,6 +92,7 @@ export class WorkflowExecutionService {
{ workflowData, runData, startNodes, destinationNode }: WorkflowRequest.ManualRunPayload,
user: User,
pushRef?: string,
partialExecutionVersion?: string,
) {
const pinData = workflowData.pinData;
const pinnedTrigger = this.selectPinnedActivatorStarter(
@@ -135,6 +136,7 @@ export class WorkflowExecutionService {
startNodes,
workflowData,
userId: user.id,
partialExecutionVersion: partialExecutionVersion ?? '0',
};
const hasRunData = (node: INode) => runData !== undefined && !!runData[node.name];

View File

@@ -43,7 +43,12 @@ export declare namespace WorkflowRequest {
type NewName = AuthenticatedRequest<{}, {}, {}, { name?: string }>;
type ManualRun = AuthenticatedRequest<{ workflowId: string }, {}, ManualRunPayload>;
type ManualRun = AuthenticatedRequest<
{ workflowId: string },
{},
ManualRunPayload,
{ partialExecutionVersion?: string }
>;
type Share = AuthenticatedRequest<{ workflowId: string }, {}, { shareWithIds: string[] }>;

View File

@@ -405,6 +405,9 @@ export class WorkflowsController {
req.body,
req.user,
req.headers['push-ref'] as string,
req.query.partialExecutionVersion === '-1'
? config.getEnv('featureFlags.partialExecutionVersionDefault')
: req.query.partialExecutionVersion,
);
}