refactor(core): Move error execution creation to execution service (no-changelog) (#8006)

Continue breaking down legacy helpers.

Note: `getUserById` is unused.
This commit is contained in:
Iván Ovejero
2023-12-21 14:15:46 +01:00
committed by GitHub
parent d1b2affd2c
commit 9ac8825a67
10 changed files with 106 additions and 110 deletions

View File

@@ -49,7 +49,7 @@ import * as WorkflowExecuteAdditionalData from '@/WorkflowExecuteAdditionalData'
import type { User } from '@db/entities/User';
import type { WorkflowEntity } from '@db/entities/WorkflowEntity';
import { ActiveExecutions } from '@/ActiveExecutions';
import { createErrorExecution } from '@/GenericHelpers';
import { ExecutionsService } from './executions/executions.service';
import {
STARTING_NODES,
WORKFLOW_REACTIVATE_INITIAL_TIMEOUT,
@@ -94,6 +94,7 @@ export class ActiveWorkflowRunner implements IWebhookManager {
private readonly sharedWorkflowRepository: SharedWorkflowRepository,
private readonly multiMainSetup: MultiMainSetup,
private readonly activationErrorsService: ActivationErrorsService,
private readonly executionService: ExecutionsService,
) {}
async init() {
@@ -547,9 +548,11 @@ export class ActiveWorkflowRunner implements IWebhookManager {
};
returnFunctions.__emitError = (error: ExecutionError): void => {
void createErrorExecution(error, node, workflowData, workflow, mode).then(() => {
this.executeErrorWorkflow(error, workflowData, mode);
});
void this.executionService
.createErrorExecution(error, node, workflowData, workflow, mode)
.then(() => {
this.executeErrorWorkflow(error, workflowData, mode);
});
};
return returnFunctions;
};

View File

@@ -1,21 +1,11 @@
import type express from 'express';
import type {
ExecutionError,
INode,
IRunExecutionData,
Workflow,
WorkflowExecuteMode,
} from 'n8n-workflow';
import { validate } from 'class-validator';
import { Container } from 'typedi';
import config from '@/config';
import type { ExecutionPayload, IWorkflowDb } from '@/Interfaces';
import type { WorkflowEntity } from '@db/entities/WorkflowEntity';
import type { CredentialsEntity } from '@db/entities/CredentialsEntity';
import type { TagEntity } from '@db/entities/TagEntity';
import type { User } from '@db/entities/User';
import type { UserUpdatePayload } from '@/requests';
import { ExecutionRepository } from '@db/repositories/execution.repository';
import { BadRequestError } from './errors/response-errors/bad-request.error';
/**
@@ -58,85 +48,4 @@ export async function validateEntity(
}
}
/**
* Create an error execution
*
* @param {INode} node
* @param {IWorkflowDb} workflowData
* @param {Workflow} workflow
* @param {WorkflowExecuteMode} mode
* @returns
* @memberof ActiveWorkflowRunner
*/
export async function createErrorExecution(
error: ExecutionError,
node: INode,
workflowData: IWorkflowDb,
workflow: Workflow,
mode: WorkflowExecuteMode,
): Promise<void> {
const saveDataErrorExecutionDisabled = workflowData?.settings?.saveDataErrorExecution === 'none';
if (saveDataErrorExecutionDisabled) return;
const executionData: IRunExecutionData = {
startData: {
destinationNode: node.name,
runNodeFilter: [node.name],
},
executionData: {
contextData: {},
metadata: {},
nodeExecutionStack: [
{
node,
data: {
main: [
[
{
json: {},
pairedItem: {
item: 0,
},
},
],
],
},
source: null,
},
],
waitingExecution: {},
waitingExecutionSource: {},
},
resultData: {
runData: {
[node.name]: [
{
startTime: 0,
executionTime: 0,
error,
source: [],
},
],
},
error,
lastNodeExecuted: node.name,
},
};
const fullExecutionData: ExecutionPayload = {
data: executionData,
mode,
finished: false,
startedAt: new Date(),
workflowData,
workflowId: workflow.id,
stoppedAt: new Date(),
status: 'error',
};
await Container.get(ExecutionRepository).createNewExecution(fullExecutionData);
}
export const DEFAULT_EXECUTIONS_GET_ALL_LIMIT = 20;

View File

@@ -6,7 +6,6 @@ import type { User } from '@db/entities/User';
import config from '@/config';
import { License } from '@/License';
import { getWebhookBaseUrl } from '@/WebhookHelpers';
import { UserRepository } from '@db/repositories/user.repository';
import type { Scope } from '@n8n/permissions';
export function isSharingEnabled(): boolean {
@@ -26,14 +25,6 @@ export function generateUserInviteUrl(inviterId: string, inviteeId: string): str
return `${getInstanceBaseUrl()}/signup?inviterId=${inviterId}&inviteeId=${inviteeId}`;
}
export async function getUserById(userId: string): Promise<User> {
const user = await Container.get(UserRepository).findOneOrFail({
where: { id: userId },
relations: ['globalRole'],
});
return user;
}
// return the difference between two arrays
export function rightDiff<T1, T2>(
[arr1, keyExtractor1]: [T1[], (item: T1) => string],

View File

@@ -35,10 +35,7 @@ export type CredentialsGetSharedOptions =
| { allowGlobalScope: false };
export class CredentialsService {
static async get(
where: FindOptionsWhere<ICredentialsDb>,
options?: { relations: string[] },
): Promise<ICredentialsDb | null> {
static async get(where: FindOptionsWhere<ICredentialsDb>, options?: { relations: string[] }) {
return Container.get(CredentialsRepository).findOne({
relations: options?.relations,
where,

View File

@@ -1,5 +1,13 @@
import { validate as jsonSchemaValidate } from 'jsonschema';
import type { IWorkflowBase, JsonObject, ExecutionStatus } from 'n8n-workflow';
import type {
IWorkflowBase,
JsonObject,
ExecutionStatus,
ExecutionError,
INode,
IRunExecutionData,
WorkflowExecuteMode,
} from 'n8n-workflow';
import { ApplicationError, jsonParse, Workflow, WorkflowOperationError } from 'n8n-workflow';
import type { FindOperator } from 'typeorm';
import { In } from 'typeorm';
@@ -7,9 +15,11 @@ import { ActiveExecutions } from '@/ActiveExecutions';
import config from '@/config';
import type { User } from '@db/entities/User';
import type {
ExecutionPayload,
IExecutionFlattedResponse,
IExecutionResponse,
IExecutionsListResponse,
IWorkflowDb,
IWorkflowExecutionDataProcess,
} from '@/Interfaces';
import { NodeTypes } from '@/NodeTypes';
@@ -18,7 +28,7 @@ import type { ExecutionRequest } from '@/requests';
import { getSharedWorkflowIds } from '@/WorkflowHelpers';
import { WorkflowRunner } from '@/WorkflowRunner';
import * as GenericHelpers from '@/GenericHelpers';
import { Container } from 'typedi';
import { Container, Service } from 'typedi';
import { getStatusUsingPreviousExecutionStatusMethod } from './executionHelpers';
import { ExecutionRepository } from '@db/repositories/execution.repository';
import { WorkflowRepository } from '@db/repositories/workflow.repository';
@@ -75,6 +85,7 @@ const schemaGetExecutionsQueryFilter = {
const allowedExecutionsQueryFilterFields = Object.keys(schemaGetExecutionsQueryFilter.properties);
@Service()
export class ExecutionsService {
/**
* Function to get the workflow Ids for a User
@@ -362,4 +373,75 @@ export class ExecutionsService {
},
);
}
async createErrorExecution(
error: ExecutionError,
node: INode,
workflowData: IWorkflowDb,
workflow: Workflow,
mode: WorkflowExecuteMode,
): Promise<void> {
const saveDataErrorExecutionDisabled =
workflowData?.settings?.saveDataErrorExecution === 'none';
if (saveDataErrorExecutionDisabled) return;
const executionData: IRunExecutionData = {
startData: {
destinationNode: node.name,
runNodeFilter: [node.name],
},
executionData: {
contextData: {},
metadata: {},
nodeExecutionStack: [
{
node,
data: {
main: [
[
{
json: {},
pairedItem: {
item: 0,
},
},
],
],
},
source: null,
},
],
waitingExecution: {},
waitingExecutionSource: {},
},
resultData: {
runData: {
[node.name]: [
{
startTime: 0,
executionTime: 0,
error,
source: [],
},
],
},
error,
lastNodeExecuted: node.name,
},
};
const fullExecutionData: ExecutionPayload = {
data: executionData,
mode,
finished: false,
startedAt: new Date(),
workflowData,
workflowId: workflow.id,
stoppedAt: new Date(),
status: 'error',
};
await Container.get(ExecutionRepository).createNewExecution(fullExecutionData);
}
}