refactor(core): Extract ExecuteContext out of NodeExecutionFunctions (no-changelog) (#11853)

This commit is contained in:
कारतोफ्फेलस्क्रिप्ट™
2024-11-26 12:10:42 +01:00
committed by GitHub
parent 3aa72f613f
commit 75e2b6fd9e
22 changed files with 1813 additions and 1940 deletions

View File

@@ -1,11 +1,6 @@
import type {
AiEvent,
CallbackManager,
CloseFunction,
ExecuteWorkflowData,
ICredentialDataDecryptedObject,
IExecuteData,
IExecuteWorkflowInfo,
IGetNodeParameterOptions,
INode,
INodeExecutionData,
@@ -15,32 +10,20 @@ import type {
ITaskMetadata,
IWorkflowExecuteAdditionalData,
NodeConnectionType,
RelatedExecution,
Workflow,
WorkflowExecuteMode,
} from 'n8n-workflow';
import {
ApplicationError,
createDeferredPromise,
NodeHelpers,
WorkflowDataProxy,
} from 'n8n-workflow';
import Container from 'typedi';
import { ApplicationError, createDeferredPromise } from 'n8n-workflow';
import { BinaryDataService } from '@/BinaryData/BinaryData.service';
// eslint-disable-next-line import/no-cycle
import {
assertBinaryData,
continueOnFail,
constructExecutionMetaData,
copyInputItems,
getAdditionalKeys,
getBinaryDataBuffer,
getBinaryHelperFunctions,
getCheckProcessedHelperFunctions,
getCredentials,
getFileSystemHelperFunctions,
getNodeParameter,
getRequestHelperFunctions,
getSSHTunnelFunctions,
normalizeItems,
@@ -49,9 +32,9 @@ import {
addExecutionDataFunctions,
} from '@/NodeExecuteFunctions';
import { NodeExecutionContext } from './node-execution-context';
import { BaseExecuteContext } from './base-execute-context';
export class SupplyDataContext extends NodeExecutionContext implements ISupplyDataFunctions {
export class SupplyDataContext extends BaseExecuteContext implements ISupplyDataFunctions {
readonly helpers: ISupplyDataFunctions['helpers'];
readonly getNodeParameter: ISupplyDataFunctions['getNodeParameter'];
@@ -61,15 +44,26 @@ export class SupplyDataContext extends NodeExecutionContext implements ISupplyDa
node: INode,
additionalData: IWorkflowExecuteAdditionalData,
mode: WorkflowExecuteMode,
private readonly runExecutionData: IRunExecutionData,
private readonly runIndex: number,
private readonly connectionInputData: INodeExecutionData[],
private readonly inputData: ITaskDataConnections,
private readonly executeData: IExecuteData,
runExecutionData: IRunExecutionData,
runIndex: number,
connectionInputData: INodeExecutionData[],
inputData: ITaskDataConnections,
executeData: IExecuteData,
private readonly closeFunctions: CloseFunction[],
private readonly abortSignal?: AbortSignal,
abortSignal?: AbortSignal,
) {
super(workflow, node, additionalData, mode);
super(
workflow,
node,
additionalData,
mode,
runExecutionData,
runIndex,
connectionInputData,
inputData,
executeData,
abortSignal,
);
this.helpers = {
createDeferredPromise,
@@ -102,116 +96,14 @@ export class SupplyDataContext extends NodeExecutionContext implements ISupplyDa
fallbackValue?: any,
options?: IGetNodeParameterOptions,
) =>
getNodeParameter(
this.workflow,
this.runExecutionData,
this.runIndex,
this.connectionInputData,
this.node,
this._getNodeParameter(
parameterName,
itemIndex,
this.mode,
getAdditionalKeys(this.additionalData, this.mode, this.runExecutionData),
this.executeData,
fallbackValue,
options,
)) as ISupplyDataFunctions['getNodeParameter'];
}
getExecutionCancelSignal() {
return this.abortSignal;
}
onExecutionCancellation(handler: () => unknown) {
const fn = () => {
this.abortSignal?.removeEventListener('abort', fn);
handler();
};
this.abortSignal?.addEventListener('abort', fn);
}
async getCredentials<T extends object = ICredentialDataDecryptedObject>(
type: string,
itemIndex: number,
) {
return await getCredentials<T>(
this.workflow,
this.node,
type,
this.additionalData,
this.mode,
this.executeData,
this.runExecutionData,
this.runIndex,
this.connectionInputData,
itemIndex,
);
}
continueOnFail() {
return continueOnFail(this.node);
}
evaluateExpression(expression: string, itemIndex: number) {
return this.workflow.expression.resolveSimpleParameterValue(
`=${expression}`,
{},
this.runExecutionData,
this.runIndex,
itemIndex,
this.node.name,
this.connectionInputData,
this.mode,
getAdditionalKeys(this.additionalData, this.mode, this.runExecutionData),
this.executeData,
);
}
async executeWorkflow(
workflowInfo: IExecuteWorkflowInfo,
inputData?: INodeExecutionData[],
parentCallbackManager?: CallbackManager,
options?: {
doNotWaitToFinish?: boolean;
parentExecution?: RelatedExecution;
},
): Promise<ExecuteWorkflowData> {
return await this.additionalData
.executeWorkflow(workflowInfo, this.additionalData, {
parentWorkflowId: this.workflow.id?.toString(),
inputData,
parentWorkflowSettings: this.workflow.settings,
node: this.node,
parentCallbackManager,
...options,
})
.then(async (result) => {
const data = await Container.get(BinaryDataService).duplicateBinaryData(
this.workflow.id,
this.additionalData.executionId!,
result.data,
);
return { ...result, data };
});
}
getNodeOutputs() {
const nodeType = this.workflow.nodeTypes.getByNameAndVersion(
this.node.type,
this.node.typeVersion,
);
return NodeHelpers.getNodeOutputs(this.workflow, this.node, nodeType.description).map(
(output) => {
if (typeof output === 'string') {
return {
type: output,
};
}
return output;
},
);
}
async getInputConnectionData(inputName: NodeConnectionType, itemIndex: number): Promise<unknown> {
return await getInputConnectionData.call(
this,
@@ -252,69 +144,11 @@ export class SupplyDataContext extends NodeExecutionContext implements ISupplyDa
return this.inputData[inputName][inputIndex];
}
getWorkflowDataProxy(itemIndex: number) {
return new WorkflowDataProxy(
this.workflow,
this.runExecutionData,
this.runIndex,
itemIndex,
this.node.name,
this.connectionInputData,
{},
this.mode,
getAdditionalKeys(this.additionalData, this.mode, this.runExecutionData),
this.executeData,
).getDataProxy();
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
sendMessageToUI(...args: any[]): void {
if (this.mode !== 'manual') {
return;
}
try {
if (this.additionalData.sendDataToUI) {
args = args.map((arg) => {
// prevent invalid dates from being logged as null
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-return
if (arg.isLuxonDateTime && arg.invalidReason) return { ...arg };
// log valid dates in human readable format, as in browser
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-argument
if (arg.isLuxonDateTime) return new Date(arg.ts).toString();
if (arg instanceof Date) return arg.toString();
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
return arg;
});
this.additionalData.sendDataToUI('sendConsoleMessage', {
source: `[Node: "${this.node.name}"]`,
messages: args,
});
}
} catch (error) {
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
this.logger.warn(`There was a problem sending message to UI: ${error.message}`);
}
}
logAiEvent(eventName: AiEvent, msg: string) {
return this.additionalData.logAiEvent(eventName, {
executionId: this.additionalData.executionId ?? 'unsaved-execution',
nodeName: this.node.name,
workflowName: this.workflow.name ?? 'Unnamed workflow',
nodeType: this.node.type,
workflowId: this.workflow.id ?? 'unsaved-workflow',
msg,
});
}
addInputData(
connectionType: NodeConnectionType,
data: INodeExecutionData[][],
): { index: number } {
const nodeName = this.getNode().name;
const nodeName = this.node.name;
let currentNodeRunIndex = 0;
if (this.runExecutionData.resultData.runData.hasOwnProperty(nodeName)) {
currentNodeRunIndex = this.runExecutionData.resultData.runData[nodeName].length;
@@ -322,17 +156,17 @@ export class SupplyDataContext extends NodeExecutionContext implements ISupplyDa
addExecutionDataFunctions(
'input',
this.node.name,
nodeName,
data,
this.runExecutionData,
connectionType,
this.additionalData,
this.node.name,
nodeName,
this.runIndex,
currentNodeRunIndex,
).catch((error) => {
this.logger.warn(
`There was a problem logging input data of node "${this.node.name}": ${
`There was a problem logging input data of node "${nodeName}": ${
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
error.message
}`,
@@ -348,20 +182,21 @@ export class SupplyDataContext extends NodeExecutionContext implements ISupplyDa
data: INodeExecutionData[][],
metadata?: ITaskMetadata,
): void {
const nodeName = this.node.name;
addExecutionDataFunctions(
'output',
this.node.name,
nodeName,
data,
this.runExecutionData,
connectionType,
this.additionalData,
this.node.name,
nodeName,
this.runIndex,
currentNodeRunIndex,
metadata,
).catch((error) => {
this.logger.warn(
`There was a problem logging output data of node "${this.node.name}": ${
`There was a problem logging output data of node "${nodeName}": ${
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
error.message
}`,