fix(core): Fix issue with not displayed child workflow executions (#3867)

This commit is contained in:
Omar Ajoue 2022-08-12 14:31:11 +02:00 committed by GitHub
parent d4b4e234a6
commit f782bcd52d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 73 additions and 24 deletions

View file

@ -31,6 +31,7 @@ import {
IWorkflowExecuteAdditionalData, IWorkflowExecuteAdditionalData,
IWorkflowExecuteHooks, IWorkflowExecuteHooks,
IWorkflowHooksOptionalParameters, IWorkflowHooksOptionalParameters,
IWorkflowSettings,
LoggerProxy as Logger, LoggerProxy as Logger,
Workflow, Workflow,
WorkflowExecuteMode, WorkflowExecuteMode,
@ -810,6 +811,8 @@ export async function getRunData(
export async function getWorkflowData( export async function getWorkflowData(
workflowInfo: IExecuteWorkflowInfo, workflowInfo: IExecuteWorkflowInfo,
userId: string, userId: string,
parentWorkflowId?: string,
parentWorkflowSettings?: IWorkflowSettings,
): Promise<IWorkflowBase> { ): Promise<IWorkflowBase> {
if (workflowInfo.id === undefined && workflowInfo.code === undefined) { if (workflowInfo.id === undefined && workflowInfo.code === undefined) {
throw new Error( throw new Error(
@ -847,6 +850,14 @@ export async function getWorkflowData(
} }
} else { } else {
workflowData = workflowInfo.code; workflowData = workflowInfo.code;
if (workflowData) {
if (!workflowData.id) {
workflowData.id = parentWorkflowId;
}
if (!workflowData.settings) {
workflowData.settings = parentWorkflowSettings;
}
}
} }
return workflowData!; return workflowData!;
@ -864,10 +875,14 @@ export async function getWorkflowData(
export async function executeWorkflow( export async function executeWorkflow(
workflowInfo: IExecuteWorkflowInfo, workflowInfo: IExecuteWorkflowInfo,
additionalData: IWorkflowExecuteAdditionalData, additionalData: IWorkflowExecuteAdditionalData,
inputData?: INodeExecutionData[], options?: {
parentExecutionId?: string, parentWorkflowId?: string;
loadedWorkflowData?: IWorkflowBase, inputData?: INodeExecutionData[];
loadedRunData?: IWorkflowExecutionDataProcess, parentExecutionId?: string;
loadedWorkflowData?: IWorkflowBase;
loadedRunData?: IWorkflowExecutionDataProcess;
parentWorkflowSettings?: IWorkflowSettings;
},
): Promise<Array<INodeExecutionData[] | null> | IWorkflowExecuteProcess> { ): Promise<Array<INodeExecutionData[] | null> | IWorkflowExecuteProcess> {
const externalHooks = ExternalHooks(); const externalHooks = ExternalHooks();
await externalHooks.init(); await externalHooks.init();
@ -875,30 +890,38 @@ export async function executeWorkflow(
const nodeTypes = NodeTypes(); const nodeTypes = NodeTypes();
const workflowData = 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 workflowName = workflowData ? workflowData.name : undefined;
const workflow = new Workflow({ const workflow = new Workflow({
id: workflowInfo.id, id: workflowData.id?.toString(),
name: workflowName, name: workflowName,
nodes: workflowData.nodes, nodes: workflowData.nodes,
connections: workflowData.connections, connections: workflowData.connections,
active: workflowData.active, active: workflowData.active,
nodeTypes, nodeTypes,
staticData: workflowData.staticData, staticData: workflowData.staticData,
settings: workflowData.settings,
}); });
const runData = const runData =
loadedRunData ?? (await getRunData(workflowData, additionalData.userId, inputData)); options?.loadedRunData ??
(await getRunData(workflowData, additionalData.userId, options?.inputData));
let executionId; let executionId;
if (parentExecutionId !== undefined) { if (options?.parentExecutionId !== undefined) {
executionId = parentExecutionId; executionId = options?.parentExecutionId;
} else { } else {
executionId = executionId =
parentExecutionId !== undefined options?.parentExecutionId !== undefined
? parentExecutionId ? options?.parentExecutionId
: await ActiveExecutions.getInstance().add(runData); : await ActiveExecutions.getInstance().add(runData);
} }
@ -946,7 +969,7 @@ export async function executeWorkflow(
runData.executionMode, runData.executionMode,
runExecutionData, runExecutionData,
); );
if (parentExecutionId !== undefined) { if (options?.parentExecutionId !== undefined) {
// Must be changed to become typed // Must be changed to become typed
return { return {
startedAt: new Date(), startedAt: new Date(),

View file

@ -247,6 +247,7 @@ export class WorkflowRunner {
active: data.workflowData.active, active: data.workflowData.active,
nodeTypes, nodeTypes,
staticData: data.workflowData.staticData, staticData: data.workflowData.staticData,
settings: data.workflowData.settings,
}); });
const additionalData = await WorkflowExecuteAdditionalData.getBase( const additionalData = await WorkflowExecuteAdditionalData.getBase(
data.userId, data.userId,

View file

@ -23,6 +23,7 @@ import {
ITaskData, ITaskData,
IWorkflowExecuteAdditionalData, IWorkflowExecuteAdditionalData,
IWorkflowExecuteHooks, IWorkflowExecuteHooks,
IWorkflowSettings,
LoggerProxy, LoggerProxy,
Workflow, Workflow,
WorkflowExecuteMode, WorkflowExecuteMode,
@ -183,6 +184,12 @@ export class WorkflowRunnerProcess {
if (Object.keys(node.credentials === undefined ? {} : node.credentials).length > 0) { if (Object.keys(node.credentials === undefined ? {} : node.credentials).length > 0) {
shouldInitializaDb = true; 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 // 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 ( additionalData.executeWorkflow = async (
workflowInfo: IExecuteWorkflowInfo, workflowInfo: IExecuteWorkflowInfo,
additionalData: IWorkflowExecuteAdditionalData, additionalData: IWorkflowExecuteAdditionalData,
inputData?: INodeExecutionData[] | undefined, options?: {
parentWorkflowId?: string;
inputData?: INodeExecutionData[];
parentWorkflowSettings?: IWorkflowSettings;
},
): Promise<Array<INodeExecutionData[] | null> | IRun> => { ): Promise<Array<INodeExecutionData[] | null> | IRun> => {
const workflowData = await WorkflowExecuteAdditionalData.getWorkflowData( const workflowData = await WorkflowExecuteAdditionalData.getWorkflowData(
workflowInfo, workflowInfo,
userId, userId,
options?.parentWorkflowId,
options?.parentWorkflowSettings,
); );
const runData = await WorkflowExecuteAdditionalData.getRunData( const runData = await WorkflowExecuteAdditionalData.getRunData(
workflowData, workflowData,
additionalData.userId, additionalData.userId,
inputData, options?.inputData,
); );
await sendToParentProcess('startExecution', { runData }); await sendToParentProcess('startExecution', { runData });
const executionId: string = await new Promise((resolve) => { const executionId: string = await new Promise((resolve) => {
@ -293,10 +306,14 @@ export class WorkflowRunnerProcess {
const executeWorkflowFunctionOutput = (await executeWorkflowFunction( const executeWorkflowFunctionOutput = (await executeWorkflowFunction(
workflowInfo, workflowInfo,
additionalData, additionalData,
inputData, {
executionId, parentWorkflowId: options?.parentWorkflowId,
workflowData, inputData: options?.inputData,
runData, parentExecutionId: executionId,
loadedWorkflowData: workflowData,
loadedRunData: runData,
parentWorkflowSettings: options?.parentWorkflowSettings,
},
)) as { workflowExecute: WorkflowExecute; workflow: Workflow } as IWorkflowExecuteProcess; )) as { workflowExecute: WorkflowExecute; workflow: Workflow } as IWorkflowExecuteProcess;
const { workflowExecute } = executeWorkflowFunctionOutput; const { workflowExecute } = executeWorkflowFunctionOutput;
this.childExecutions[executionId] = executeWorkflowFunctionOutput; this.childExecutions[executionId] = executeWorkflowFunctionOutput;

View file

@ -2199,7 +2199,11 @@ export function getExecuteFunctions(
inputData?: INodeExecutionData[], inputData?: INodeExecutionData[],
): Promise<any> { ): Promise<any> {
return additionalData return additionalData
.executeWorkflow(workflowInfo, additionalData, inputData) .executeWorkflow(workflowInfo, additionalData, {
parentWorkflowId: workflow.id?.toString(),
inputData,
parentWorkflowSettings: workflow.settings,
})
.then(async (result) => .then(async (result) =>
BinaryDataManager.getInstance().duplicateBinaryData( BinaryDataManager.getInstance().duplicateBinaryData(
result, result,

View file

@ -1437,10 +1437,14 @@ export interface IWorkflowExecuteAdditionalData {
executeWorkflow: ( executeWorkflow: (
workflowInfo: IExecuteWorkflowInfo, workflowInfo: IExecuteWorkflowInfo,
additionalData: IWorkflowExecuteAdditionalData, additionalData: IWorkflowExecuteAdditionalData,
inputData?: INodeExecutionData[], options?: {
parentExecutionId?: string, parentWorkflowId?: string;
loadedWorkflowData?: IWorkflowBase, inputData?: INodeExecutionData[];
loadedRunData?: any, parentExecutionId?: string;
loadedWorkflowData?: IWorkflowBase;
loadedRunData?: any;
parentWorkflowSettings?: IWorkflowSettings;
},
) => Promise<any>; ) => Promise<any>;
// hooks?: IWorkflowExecuteHooks; // hooks?: IWorkflowExecuteHooks;
executionId?: string; executionId?: string;

View file

@ -217,7 +217,7 @@ export function getExecuteFunctions(
workflowInfo: IExecuteWorkflowInfo, workflowInfo: IExecuteWorkflowInfo,
inputData?: INodeExecutionData[], inputData?: INodeExecutionData[],
): Promise<any> { ): Promise<any> {
return additionalData.executeWorkflow(workflowInfo, additionalData, inputData); return additionalData.executeWorkflow(workflowInfo, additionalData, { inputData });
}, },
getContext(type: string): IContextObject { getContext(type: string): IContextObject {
return NodeHelpers.getContext(runExecutionData, type, node); return NodeHelpers.getContext(runExecutionData, type, node);