mirror of
https://github.com/Abdulazizzn/n8n-enterprise-unlocked.git
synced 2025-12-17 01:56:46 +00:00
perf(core): Batch items sent in runonceforeachitem mode (no-changelog) (#11870)
Co-authored-by: Iván Ovejero <ivov.src@gmail.com>
This commit is contained in:
@@ -19,7 +19,12 @@ import * as a from 'node:assert';
|
||||
import { runInNewContext, type Context } from 'node:vm';
|
||||
|
||||
import type { MainConfig } from '@/config/main-config';
|
||||
import type { DataRequestResponse, PartialAdditionalData, TaskResultData } from '@/runner-types';
|
||||
import type {
|
||||
DataRequestResponse,
|
||||
InputDataChunkDefinition,
|
||||
PartialAdditionalData,
|
||||
TaskResultData,
|
||||
} from '@/runner-types';
|
||||
import { type Task, TaskRunner } from '@/task-runner';
|
||||
|
||||
import { BuiltInsParser } from './built-ins-parser/built-ins-parser';
|
||||
@@ -37,9 +42,8 @@ export interface JSExecSettings {
|
||||
nodeMode: CodeExecutionMode;
|
||||
workflowMode: WorkflowExecuteMode;
|
||||
continueOnFail: boolean;
|
||||
|
||||
// For workflow data proxy
|
||||
mode: WorkflowExecuteMode;
|
||||
// For executing partial input data
|
||||
chunk?: InputDataChunkDefinition;
|
||||
}
|
||||
|
||||
export interface JsTaskData {
|
||||
@@ -94,6 +98,8 @@ export class JsTaskRunner extends TaskRunner {
|
||||
const settings = task.settings;
|
||||
a.ok(settings, 'JS Code not sent to runner');
|
||||
|
||||
this.validateTaskSettings(settings);
|
||||
|
||||
const neededBuiltInsResult = this.builtInsParser.parseUsedBuiltIns(settings.code);
|
||||
const neededBuiltIns = neededBuiltInsResult.ok
|
||||
? neededBuiltInsResult.result
|
||||
@@ -101,10 +107,10 @@ export class JsTaskRunner extends TaskRunner {
|
||||
|
||||
const dataResponse = await this.requestData<DataRequestResponse>(
|
||||
task.taskId,
|
||||
neededBuiltIns.toDataRequestParams(),
|
||||
neededBuiltIns.toDataRequestParams(settings.chunk),
|
||||
);
|
||||
|
||||
const data = this.reconstructTaskData(dataResponse);
|
||||
const data = this.reconstructTaskData(dataResponse, settings.chunk);
|
||||
|
||||
await this.requestNodeTypeIfNeeded(neededBuiltIns, data.workflow, task.taskId);
|
||||
|
||||
@@ -136,6 +142,14 @@ export class JsTaskRunner extends TaskRunner {
|
||||
};
|
||||
}
|
||||
|
||||
private validateTaskSettings(settings: JSExecSettings) {
|
||||
a.ok(settings.code, 'No code to execute');
|
||||
|
||||
if (settings.nodeMode === 'runOnceForAllItems') {
|
||||
a.ok(settings.chunk === undefined, 'Chunking is not supported for runOnceForAllItems');
|
||||
}
|
||||
}
|
||||
|
||||
private getNativeVariables() {
|
||||
return {
|
||||
// Exposed Node.js globals in vm2
|
||||
@@ -220,7 +234,13 @@ export class JsTaskRunner extends TaskRunner {
|
||||
const inputItems = data.connectionInputData;
|
||||
const returnData: INodeExecutionData[] = [];
|
||||
|
||||
for (let index = 0; index < inputItems.length; index++) {
|
||||
// If a chunk was requested, only process the items in the chunk
|
||||
const chunkStartIdx = settings.chunk ? settings.chunk.startIndex : 0;
|
||||
const chunkEndIdx = settings.chunk
|
||||
? settings.chunk.startIndex + settings.chunk.count
|
||||
: inputItems.length;
|
||||
|
||||
for (let index = chunkStartIdx; index < chunkEndIdx; index++) {
|
||||
const item = inputItems[index];
|
||||
const dataProxy = this.createDataProxy(data, workflow, index);
|
||||
const context: Context = {
|
||||
@@ -325,13 +345,24 @@ export class JsTaskRunner extends TaskRunner {
|
||||
return new ExecutionError({ message: JSON.stringify(error) });
|
||||
}
|
||||
|
||||
private reconstructTaskData(response: DataRequestResponse): JsTaskData {
|
||||
private reconstructTaskData(
|
||||
response: DataRequestResponse,
|
||||
chunk?: InputDataChunkDefinition,
|
||||
): JsTaskData {
|
||||
const inputData = this.taskDataReconstruct.reconstructConnectionInputItems(
|
||||
response.inputData,
|
||||
chunk,
|
||||
// This type assertion is intentional. Chunking is only supported in
|
||||
// runOnceForEachItem mode and if a chunk was requested, we intentionally
|
||||
// fill the array with undefined values for the items outside the chunk.
|
||||
// We only iterate over the chunk items but WorkflowDataProxy expects
|
||||
// the full array of items.
|
||||
) as INodeExecutionData[];
|
||||
|
||||
return {
|
||||
...response,
|
||||
connectionInputData: this.taskDataReconstruct.reconstructConnectionInputData(
|
||||
response.inputData,
|
||||
),
|
||||
executeData: this.taskDataReconstruct.reconstructExecuteData(response),
|
||||
connectionInputData: inputData,
|
||||
executeData: this.taskDataReconstruct.reconstructExecuteData(response, inputData),
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user