From b86fc8748058991ec3041bba3888cbba1cc0b734 Mon Sep 17 00:00:00 2001 From: Omar Ajoue Date: Thu, 11 Aug 2022 09:58:30 +0200 Subject: [PATCH] Assign parent workflow ID to subworkflows from generic JSON --- .../cli/src/WorkflowExecuteAdditionalData.ts | 47 ++++++++++++++----- packages/cli/src/WorkflowRunner.ts | 1 + packages/cli/src/WorkflowRunnerProcess.ts | 29 +++++++++--- packages/core/src/NodeExecuteFunctions.ts | 6 ++- packages/workflow/src/Interfaces.ts | 12 +++-- packages/workflow/test/Helpers.ts | 2 +- 6 files changed, 73 insertions(+), 24 deletions(-) diff --git a/packages/cli/src/WorkflowExecuteAdditionalData.ts b/packages/cli/src/WorkflowExecuteAdditionalData.ts index 2152d7b51b1ed..98e1b408e5924 100644 --- a/packages/cli/src/WorkflowExecuteAdditionalData.ts +++ b/packages/cli/src/WorkflowExecuteAdditionalData.ts @@ -31,6 +31,7 @@ import { IWorkflowExecuteAdditionalData, IWorkflowExecuteHooks, IWorkflowHooksOptionalParameters, + IWorkflowSettings, LoggerProxy as Logger, Workflow, WorkflowExecuteMode, @@ -810,6 +811,8 @@ export async function getRunData( export async function getWorkflowData( workflowInfo: IExecuteWorkflowInfo, userId: string, + parentWorkflowId?: string, + parentWorkflowSettings?: IWorkflowSettings, ): Promise { if (workflowInfo.id === undefined && workflowInfo.code === undefined) { throw new Error( @@ -847,6 +850,14 @@ export async function getWorkflowData( } } else { workflowData = workflowInfo.code; + if (workflowData) { + if (!workflowData.id) { + workflowData.id = parentWorkflowId; + } + if (!workflowData.settings) { + workflowData.settings = parentWorkflowSettings; + } + } } return workflowData!; @@ -864,10 +875,14 @@ export async function getWorkflowData( export async function executeWorkflow( workflowInfo: IExecuteWorkflowInfo, additionalData: IWorkflowExecuteAdditionalData, - inputData?: INodeExecutionData[], - parentExecutionId?: string, - loadedWorkflowData?: IWorkflowBase, - loadedRunData?: IWorkflowExecutionDataProcess, + options?: { + parentWorkflowId?: string; + inputData?: INodeExecutionData[]; + parentExecutionId?: string; + loadedWorkflowData?: IWorkflowBase; + loadedRunData?: IWorkflowExecutionDataProcess; + parentWorkflowSettings?: IWorkflowSettings; + }, ): Promise | IWorkflowExecuteProcess> { const externalHooks = ExternalHooks(); await externalHooks.init(); @@ -875,30 +890,38 @@ export async function executeWorkflow( const nodeTypes = NodeTypes(); const workflowData = - loadedWorkflowData ?? (await getWorkflowData(workflowInfo, additionalData.userId)); + options?.loadedWorkflowData ?? + (await getWorkflowData( + workflowInfo, + additionalData.userId, + options?.parentWorkflowId, + options?.parentWorkflowSettings, + )); const workflowName = workflowData ? workflowData.name : undefined; const workflow = new Workflow({ - id: workflowInfo.id, + id: workflowData.id?.toString(), name: workflowName, nodes: workflowData.nodes, connections: workflowData.connections, active: workflowData.active, nodeTypes, staticData: workflowData.staticData, + settings: workflowData.settings, }); const runData = - loadedRunData ?? (await getRunData(workflowData, additionalData.userId, inputData)); + options?.loadedRunData ?? + (await getRunData(workflowData, additionalData.userId, options?.inputData)); let executionId; - if (parentExecutionId !== undefined) { - executionId = parentExecutionId; + if (options?.parentExecutionId !== undefined) { + executionId = options?.parentExecutionId; } else { executionId = - parentExecutionId !== undefined - ? parentExecutionId + options?.parentExecutionId !== undefined + ? options?.parentExecutionId : await ActiveExecutions.getInstance().add(runData); } @@ -946,7 +969,7 @@ export async function executeWorkflow( runData.executionMode, runExecutionData, ); - if (parentExecutionId !== undefined) { + if (options?.parentExecutionId !== undefined) { // Must be changed to become typed return { startedAt: new Date(), diff --git a/packages/cli/src/WorkflowRunner.ts b/packages/cli/src/WorkflowRunner.ts index 2af9d77405d10..897da83457c47 100644 --- a/packages/cli/src/WorkflowRunner.ts +++ b/packages/cli/src/WorkflowRunner.ts @@ -247,6 +247,7 @@ export class WorkflowRunner { active: data.workflowData.active, nodeTypes, staticData: data.workflowData.staticData, + settings: data.workflowData.settings, }); const additionalData = await WorkflowExecuteAdditionalData.getBase( data.userId, diff --git a/packages/cli/src/WorkflowRunnerProcess.ts b/packages/cli/src/WorkflowRunnerProcess.ts index 739778a3f8ca4..ccedf6f4672a3 100644 --- a/packages/cli/src/WorkflowRunnerProcess.ts +++ b/packages/cli/src/WorkflowRunnerProcess.ts @@ -23,6 +23,7 @@ import { ITaskData, IWorkflowExecuteAdditionalData, IWorkflowExecuteHooks, + IWorkflowSettings, LoggerProxy, Workflow, WorkflowExecuteMode, @@ -183,6 +184,12 @@ export class WorkflowRunnerProcess { if (Object.keys(node.credentials === undefined ? {} : node.credentials).length > 0) { shouldInitializaDb = true; } + if (node.type === 'n8n-nodes-base.executeWorkflow') { + // With UM, child workflows from arbitrary JSON + // Should be persisted by the child process, + // so DB needs to be initialized + shouldInitializaDb = true; + } }); // This code has been split into 4 ifs just to make it easier to understand @@ -271,16 +278,22 @@ export class WorkflowRunnerProcess { additionalData.executeWorkflow = async ( workflowInfo: IExecuteWorkflowInfo, additionalData: IWorkflowExecuteAdditionalData, - inputData?: INodeExecutionData[] | undefined, + options?: { + parentWorkflowId?: string; + inputData?: INodeExecutionData[]; + parentWorkflowSettings?: IWorkflowSettings; + }, ): Promise | IRun> => { const workflowData = await WorkflowExecuteAdditionalData.getWorkflowData( workflowInfo, userId, + options?.parentWorkflowId, + options?.parentWorkflowSettings, ); const runData = await WorkflowExecuteAdditionalData.getRunData( workflowData, additionalData.userId, - inputData, + options?.inputData, ); await sendToParentProcess('startExecution', { runData }); const executionId: string = await new Promise((resolve) => { @@ -293,10 +306,14 @@ export class WorkflowRunnerProcess { const executeWorkflowFunctionOutput = (await executeWorkflowFunction( workflowInfo, additionalData, - inputData, - executionId, - workflowData, - runData, + { + parentWorkflowId: options?.parentWorkflowId, + inputData: options?.inputData, + parentExecutionId: executionId, + loadedWorkflowData: workflowData, + loadedRunData: runData, + parentWorkflowSettings: options?.parentWorkflowSettings, + }, )) as { workflowExecute: WorkflowExecute; workflow: Workflow } as IWorkflowExecuteProcess; const { workflowExecute } = executeWorkflowFunctionOutput; this.childExecutions[executionId] = executeWorkflowFunctionOutput; diff --git a/packages/core/src/NodeExecuteFunctions.ts b/packages/core/src/NodeExecuteFunctions.ts index c1b4db146f1fe..11240779d06ae 100644 --- a/packages/core/src/NodeExecuteFunctions.ts +++ b/packages/core/src/NodeExecuteFunctions.ts @@ -2199,7 +2199,11 @@ export function getExecuteFunctions( inputData?: INodeExecutionData[], ): Promise { return additionalData - .executeWorkflow(workflowInfo, additionalData, inputData) + .executeWorkflow(workflowInfo, additionalData, { + parentWorkflowId: workflow.id?.toString(), + inputData, + parentWorkflowSettings: workflow.settings, + }) .then(async (result) => BinaryDataManager.getInstance().duplicateBinaryData( result, diff --git a/packages/workflow/src/Interfaces.ts b/packages/workflow/src/Interfaces.ts index af84d154c5185..501b29c5c7d7d 100644 --- a/packages/workflow/src/Interfaces.ts +++ b/packages/workflow/src/Interfaces.ts @@ -1437,10 +1437,14 @@ export interface IWorkflowExecuteAdditionalData { executeWorkflow: ( workflowInfo: IExecuteWorkflowInfo, additionalData: IWorkflowExecuteAdditionalData, - inputData?: INodeExecutionData[], - parentExecutionId?: string, - loadedWorkflowData?: IWorkflowBase, - loadedRunData?: any, + options?: { + parentWorkflowId?: string; + inputData?: INodeExecutionData[]; + parentExecutionId?: string; + loadedWorkflowData?: IWorkflowBase; + loadedRunData?: any; + parentWorkflowSettings?: IWorkflowSettings; + }, ) => Promise; // hooks?: IWorkflowExecuteHooks; executionId?: string; diff --git a/packages/workflow/test/Helpers.ts b/packages/workflow/test/Helpers.ts index bee0476d32766..635f29a68e4fa 100644 --- a/packages/workflow/test/Helpers.ts +++ b/packages/workflow/test/Helpers.ts @@ -217,7 +217,7 @@ export function getExecuteFunctions( workflowInfo: IExecuteWorkflowInfo, inputData?: INodeExecutionData[], ): Promise { - return additionalData.executeWorkflow(workflowInfo, additionalData, inputData); + return additionalData.executeWorkflow(workflowInfo, additionalData, { inputData }); }, getContext(type: string): IContextObject { return NodeHelpers.getContext(runExecutionData, type, node);