mirror of
https://github.com/Abdulazizzn/n8n-enterprise-unlocked.git
synced 2025-12-16 09:36:44 +00:00
feat(core): Link 'Error Trigger' nodes to the parent execution that errored (#16016)
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
import type { User } from '@n8n/db';
|
||||
import type { GlobalConfig } from '@n8n/config';
|
||||
import type { Project, User, WorkflowEntity, WorkflowRepository } from '@n8n/db';
|
||||
import { mock } from 'jest-mock-extended';
|
||||
import {
|
||||
NodeConnectionTypes,
|
||||
@@ -7,8 +8,10 @@ import {
|
||||
type INodeType,
|
||||
type IWorkflowBase,
|
||||
type IWorkflowExecuteAdditionalData,
|
||||
type ExecutionError,
|
||||
} from 'n8n-workflow';
|
||||
|
||||
import type { IWorkflowErrorData } from '@/interfaces';
|
||||
import type { NodeTypes } from '@/node-types';
|
||||
import * as WorkflowExecuteAdditionalData from '@/workflow-execute-additional-data';
|
||||
import type { WorkflowRunner } from '@/workflow-runner';
|
||||
@@ -490,6 +493,113 @@ describe('WorkflowExecutionService', () => {
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('executeErrorWorkflow()', () => {
|
||||
test('should call `WorkflowRunner.run()` with correct parameters', async () => {
|
||||
const workflowErrorData: IWorkflowErrorData = {
|
||||
workflow: { id: 'workflow-id', name: 'Test Workflow' },
|
||||
execution: {
|
||||
id: 'execution-id',
|
||||
mode: 'manual',
|
||||
error: new Error('Test error') as ExecutionError,
|
||||
lastNodeExecuted: 'Node with error',
|
||||
},
|
||||
};
|
||||
|
||||
const workflowRunnerMock = mock<WorkflowRunner>();
|
||||
workflowRunnerMock.run.mockResolvedValue('fake-execution-id');
|
||||
|
||||
const errorTriggerType = 'n8n-nodes-base.errorTrigger';
|
||||
const globalConfig = mock<GlobalConfig>({
|
||||
nodes: {
|
||||
errorTriggerType,
|
||||
},
|
||||
});
|
||||
|
||||
const errorTriggerNode: INode = {
|
||||
id: 'error-trigger-node-id',
|
||||
name: 'Error Trigger',
|
||||
type: errorTriggerType,
|
||||
typeVersion: 1,
|
||||
position: [0, 0],
|
||||
parameters: {},
|
||||
};
|
||||
|
||||
const errorWorkflow = mock<WorkflowEntity>({
|
||||
id: 'error-workflow-id',
|
||||
name: 'Error Workflow',
|
||||
active: false,
|
||||
isArchived: false,
|
||||
pinData: {},
|
||||
nodes: [errorTriggerNode],
|
||||
connections: {},
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
});
|
||||
|
||||
const workflowRepositoryMock = mock<WorkflowRepository>();
|
||||
workflowRepositoryMock.findOneBy.mockResolvedValue(errorWorkflow);
|
||||
|
||||
const service = new WorkflowExecutionService(
|
||||
mock(),
|
||||
mock(),
|
||||
mock(),
|
||||
workflowRepositoryMock,
|
||||
nodeTypes,
|
||||
mock(),
|
||||
workflowRunnerMock,
|
||||
globalConfig,
|
||||
mock(),
|
||||
mock(),
|
||||
);
|
||||
|
||||
await service.executeErrorWorkflow(
|
||||
'error-workflow-id',
|
||||
workflowErrorData,
|
||||
mock<Project>({ id: 'project-id' }),
|
||||
);
|
||||
|
||||
expect(workflowRunnerMock.run).toHaveBeenCalledTimes(1);
|
||||
expect(workflowRunnerMock.run).toHaveBeenCalledWith({
|
||||
executionMode: 'error',
|
||||
executionData: {
|
||||
executionData: {
|
||||
contextData: {},
|
||||
metadata: {},
|
||||
nodeExecutionStack: [
|
||||
{
|
||||
node: errorTriggerNode,
|
||||
data: {
|
||||
main: [
|
||||
[
|
||||
{
|
||||
json: workflowErrorData,
|
||||
},
|
||||
],
|
||||
],
|
||||
},
|
||||
source: null,
|
||||
metadata: {
|
||||
parentExecution: {
|
||||
executionId: 'execution-id',
|
||||
workflowId: 'workflow-id',
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
waitingExecution: {},
|
||||
waitingExecutionSource: {},
|
||||
},
|
||||
resultData: {
|
||||
runData: {},
|
||||
},
|
||||
startData: {},
|
||||
},
|
||||
workflowData: errorWorkflow,
|
||||
projectId: 'project-id',
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
function createMainConnection(targetNode: string, sourceNode: string): IConnections {
|
||||
|
||||
@@ -320,6 +320,14 @@ export class WorkflowExecutionService {
|
||||
return;
|
||||
}
|
||||
|
||||
const parentExecution =
|
||||
workflowErrorData.execution?.id && workflowErrorData.workflow?.id
|
||||
? {
|
||||
executionId: workflowErrorData.execution.id,
|
||||
workflowId: workflowErrorData.workflow.id,
|
||||
}
|
||||
: undefined;
|
||||
|
||||
// Can execute without webhook so go on
|
||||
// Initialize the data of the webhook node
|
||||
const nodeExecutionStack: IExecuteData[] = [];
|
||||
@@ -335,6 +343,11 @@ export class WorkflowExecutionService {
|
||||
],
|
||||
},
|
||||
source: null,
|
||||
...(parentExecution && {
|
||||
metadata: {
|
||||
parentExecution,
|
||||
},
|
||||
}),
|
||||
});
|
||||
|
||||
const runExecutionData: IRunExecutionData = {
|
||||
|
||||
Reference in New Issue
Block a user