mirror of
https://github.com/n8n-io/n8n
synced 2026-04-21 15:47:20 +00:00
fix(core): Force full execution data fetching for evaluation test runs (#27335)
This commit is contained in:
parent
3ad5926a5e
commit
87afcd8db4
6 changed files with 87 additions and 2 deletions
15
.vscode/launch.json
vendored
15
.vscode/launch.json
vendored
|
|
@ -32,6 +32,21 @@
|
||||||
"outputCapture": "std",
|
"outputCapture": "std",
|
||||||
"killBehavior": "forceful"
|
"killBehavior": "forceful"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "Launch n8n CLI worker dev with debug",
|
||||||
|
"runtimeExecutable": "pnpm",
|
||||||
|
"cwd": "${workspaceFolder}/packages/cli",
|
||||||
|
"runtimeArgs": ["run", "dev:worker", "--", "--inspect-brk"],
|
||||||
|
"console": "integratedTerminal",
|
||||||
|
"restart": true,
|
||||||
|
"autoAttachChildProcesses": true,
|
||||||
|
"request": "launch",
|
||||||
|
"skipFiles": ["<node_internals>/**"],
|
||||||
|
"type": "node",
|
||||||
|
"envFile": "${workspaceFolder}/.env",
|
||||||
|
"outputCapture": "std",
|
||||||
|
"killBehavior": "polite"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "Launch n8n CLI dev with debug",
|
"name": "Launch n8n CLI dev with debug",
|
||||||
"runtimeExecutable": "pnpm",
|
"runtimeExecutable": "pnpm",
|
||||||
|
|
|
||||||
|
|
@ -572,6 +572,57 @@ describe('workflow timeout with startedAt', () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('needsFullExecutionData', () => {
|
||||||
|
const originalEnv = process.env.N8N_MINIMIZE_EXECUTION_DATA_FETCHING;
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
if (originalEnv === undefined) {
|
||||||
|
delete process.env.N8N_MINIMIZE_EXECUTION_DATA_FETCHING;
|
||||||
|
} else {
|
||||||
|
process.env.N8N_MINIMIZE_EXECUTION_DATA_FETCHING = originalEnv;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return true when forceFullExecutionData is true even with N8N_MINIMIZE_EXECUTION_DATA_FETCHING set', () => {
|
||||||
|
process.env.N8N_MINIMIZE_EXECUTION_DATA_FETCHING = 'true';
|
||||||
|
|
||||||
|
// @ts-expect-error Private method
|
||||||
|
const result = runner.needsFullExecutionData('evaluation', 'exec-id', true);
|
||||||
|
|
||||||
|
expect(result).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return true when env var is not set and forceFullExecutionData is undefined', () => {
|
||||||
|
delete process.env.N8N_MINIMIZE_EXECUTION_DATA_FETCHING;
|
||||||
|
|
||||||
|
// @ts-expect-error Private method
|
||||||
|
const result = runner.needsFullExecutionData('webhook', 'exec-id', undefined);
|
||||||
|
|
||||||
|
expect(result).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return false when env var is set, forceFullExecutionData is undefined, and mode is not integrated', () => {
|
||||||
|
process.env.N8N_MINIMIZE_EXECUTION_DATA_FETCHING = 'true';
|
||||||
|
|
||||||
|
const activeExecutions = Container.get(ActiveExecutions);
|
||||||
|
jest.spyOn(activeExecutions, 'getResponseMode').mockReturnValue('responseNode');
|
||||||
|
|
||||||
|
// @ts-expect-error Private method
|
||||||
|
const result = runner.needsFullExecutionData('webhook', 'exec-id', undefined);
|
||||||
|
|
||||||
|
expect(result).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return true when env var is set and mode is integrated', () => {
|
||||||
|
process.env.N8N_MINIMIZE_EXECUTION_DATA_FETCHING = 'true';
|
||||||
|
|
||||||
|
// @ts-expect-error Private method
|
||||||
|
const result = runner.needsFullExecutionData('integrated', 'exec-id', undefined);
|
||||||
|
|
||||||
|
expect(result).toBe(true);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe('streaming functionality', () => {
|
describe('streaming functionality', () => {
|
||||||
it('should setup sendChunk handler when streaming is enabled and execution mode is not manual', async () => {
|
it('should setup sendChunk handler when streaming is enabled and execution mode is not manual', async () => {
|
||||||
// ARRANGE
|
// ARRANGE
|
||||||
|
|
|
||||||
|
|
@ -489,6 +489,7 @@ describe('TestRunnerService', () => {
|
||||||
resource: 'dataset',
|
resource: 'dataset',
|
||||||
operation: 'getRows',
|
operation: 'getRows',
|
||||||
});
|
});
|
||||||
|
expect(runCallArg).toHaveProperty('forceFullExecutionData', true);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should call workflowRunner.run with correct data in queue execution mode and manual offload', async () => {
|
test('should call workflowRunner.run with correct data in queue execution mode and manual offload', async () => {
|
||||||
|
|
@ -575,6 +576,7 @@ describe('TestRunnerService', () => {
|
||||||
resource: 'dataset',
|
resource: 'dataset',
|
||||||
operation: 'getRows',
|
operation: 'getRows',
|
||||||
});
|
});
|
||||||
|
expect(runCallArg).toHaveProperty('forceFullExecutionData', true);
|
||||||
|
|
||||||
// after reset
|
// after reset
|
||||||
delete process.env.OFFLOAD_MANUAL_EXECUTIONS_TO_WORKERS;
|
delete process.env.OFFLOAD_MANUAL_EXECUTIONS_TO_WORKERS;
|
||||||
|
|
@ -742,6 +744,7 @@ describe('TestRunnerService', () => {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
userId: metadata.userId,
|
userId: metadata.userId,
|
||||||
|
forceFullExecutionData: true,
|
||||||
triggerToStartFrom: {
|
triggerToStartFrom: {
|
||||||
name: triggerNodeName,
|
name: triggerNodeName,
|
||||||
},
|
},
|
||||||
|
|
@ -869,6 +872,7 @@ describe('TestRunnerService', () => {
|
||||||
expect(runCallArg).toEqual(
|
expect(runCallArg).toEqual(
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
executionMode: 'evaluation',
|
executionMode: 'evaluation',
|
||||||
|
forceFullExecutionData: true,
|
||||||
pinData: {
|
pinData: {
|
||||||
[triggerNodeName]: [testCase],
|
[triggerNodeName]: [testCase],
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -250,6 +250,7 @@ export class TestRunnerService {
|
||||||
const data: IWorkflowExecutionDataProcess = {
|
const data: IWorkflowExecutionDataProcess = {
|
||||||
executionMode: 'evaluation',
|
executionMode: 'evaluation',
|
||||||
pinData,
|
pinData,
|
||||||
|
forceFullExecutionData: true,
|
||||||
workflowData: {
|
workflowData: {
|
||||||
...workflow,
|
...workflow,
|
||||||
settings: {
|
settings: {
|
||||||
|
|
@ -336,6 +337,7 @@ export class TestRunnerService {
|
||||||
destinationNode: { nodeName: triggerNode.name, mode: 'inclusive' },
|
destinationNode: { nodeName: triggerNode.name, mode: 'inclusive' },
|
||||||
executionMode: 'manual',
|
executionMode: 'manual',
|
||||||
runData: {},
|
runData: {},
|
||||||
|
forceFullExecutionData: true,
|
||||||
workflowData: {
|
workflowData: {
|
||||||
...workflow,
|
...workflow,
|
||||||
settings: {
|
settings: {
|
||||||
|
|
|
||||||
|
|
@ -489,7 +489,10 @@ export class WorkflowRunner {
|
||||||
|
|
||||||
let runData: IRun;
|
let runData: IRun;
|
||||||
|
|
||||||
if (!jobResult || this.needsFullExecutionData(data.executionMode, executionId)) {
|
if (
|
||||||
|
!jobResult ||
|
||||||
|
this.needsFullExecutionData(data.executionMode, executionId, data.forceFullExecutionData)
|
||||||
|
) {
|
||||||
const fullExecutionData = await this.executionRepository.findSingleExecution(
|
const fullExecutionData = await this.executionRepository.findSingleExecution(
|
||||||
executionId,
|
executionId,
|
||||||
{
|
{
|
||||||
|
|
@ -561,7 +564,12 @@ export class WorkflowRunner {
|
||||||
* In all other cases we can skip the DB fetch and use the lightweight
|
* In all other cases we can skip the DB fetch and use the lightweight
|
||||||
* result summary sent by the worker via the job progress message.
|
* result summary sent by the worker via the job progress message.
|
||||||
*/
|
*/
|
||||||
private needsFullExecutionData(executionMode: WorkflowExecuteMode, executionId: string): boolean {
|
private needsFullExecutionData(
|
||||||
|
executionMode: WorkflowExecuteMode,
|
||||||
|
executionId: string,
|
||||||
|
forceFullExecutionData?: boolean,
|
||||||
|
): boolean {
|
||||||
|
if (forceFullExecutionData) return true;
|
||||||
if (!process.env.N8N_MINIMIZE_EXECUTION_DATA_FETCHING) return true;
|
if (!process.env.N8N_MINIMIZE_EXECUTION_DATA_FETCHING) return true;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
|
||||||
|
|
@ -2880,6 +2880,11 @@ export interface IWorkflowExecutionDataProcess {
|
||||||
destinationNode?: IDestinationNode;
|
destinationNode?: IDestinationNode;
|
||||||
restartExecutionId?: string;
|
restartExecutionId?: string;
|
||||||
executionMode: WorkflowExecuteMode;
|
executionMode: WorkflowExecuteMode;
|
||||||
|
/**
|
||||||
|
* When true, forces the execution data to be present in the run data
|
||||||
|
* ignores N8N_MINIMIZE_EXECUTION_DATA_FETCHING environment variable if set
|
||||||
|
*/
|
||||||
|
forceFullExecutionData?: boolean;
|
||||||
/**
|
/**
|
||||||
* The data that is sent in the body of the webhook that started this
|
* The data that is sent in the body of the webhook that started this
|
||||||
* execution.
|
* execution.
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue