mirror of
https://github.com/Abdulazizzn/n8n-enterprise-unlocked.git
synced 2025-12-17 18:12:04 +00:00
refactor(core): Use an IoC container to manage singleton classes [Part-1] (no-changelog) (#5509)
* add typedi * convert ActiveWorkflowRunner into an injectable service * convert ExternalHooks into an injectable service * convert InternalHooks into an injectable service * convert LoadNodesAndCredentials into an injectable service * convert NodeTypes and CredentialTypes into an injectable service * convert ActiveExecutions into an injectable service * convert WaitTracker into an injectable service * convert Push into an injectable service * convert ActiveWebhooks and TestWebhooks into an injectable services * handle circular references, and log errors when a circular dependency is found
This commit is contained in:
committed by
GitHub
parent
aca94bb995
commit
52f740b9e8
@@ -8,6 +8,8 @@
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-call */
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
||||
|
||||
import { Container, Service } from 'typedi';
|
||||
import { ActiveWorkflows, NodeExecuteFunctions } from 'n8n-core';
|
||||
|
||||
import type {
|
||||
@@ -55,7 +57,7 @@ import config from '@/config';
|
||||
import type { User } from '@db/entities/User';
|
||||
import type { WorkflowEntity } from '@db/entities/WorkflowEntity';
|
||||
import type { WebhookEntity } from '@db/entities/WebhookEntity';
|
||||
import * as ActiveExecutions from '@/ActiveExecutions';
|
||||
import { ActiveExecutions } from '@/ActiveExecutions';
|
||||
import { createErrorExecution } from '@/GenericHelpers';
|
||||
import { WORKFLOW_REACTIVATE_INITIAL_TIMEOUT, WORKFLOW_REACTIVATE_MAX_TIMEOUT } from '@/constants';
|
||||
import { NodeTypes } from '@/NodeTypes';
|
||||
@@ -68,8 +70,9 @@ import { START_NODES } from './constants';
|
||||
const WEBHOOK_PROD_UNREGISTERED_HINT =
|
||||
"The workflow must be active for a production URL to run successfully. You can activate the workflow using the toggle in the top-right of the editor. Note that unlike test URL calls, production URL calls aren't shown on the canvas (only in the executions list)";
|
||||
|
||||
@Service()
|
||||
export class ActiveWorkflowRunner {
|
||||
private activeWorkflows: ActiveWorkflows | null = null;
|
||||
private activeWorkflows = new ActiveWorkflows();
|
||||
|
||||
private activationErrors: {
|
||||
[key: string]: IActivationError;
|
||||
@@ -79,9 +82,7 @@ export class ActiveWorkflowRunner {
|
||||
[key: string]: IQueuedWorkflowActivations;
|
||||
} = {};
|
||||
|
||||
constructor() {
|
||||
this.activeWorkflows = new ActiveWorkflows();
|
||||
}
|
||||
constructor(private externalHooks: ExternalHooks) {}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
||||
async init() {
|
||||
@@ -133,7 +134,7 @@ export class ActiveWorkflowRunner {
|
||||
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
|
||||
Logger.info(` ${error.message}`);
|
||||
Logger.error(
|
||||
`Issue on intital workflow activation try "${workflowData.name}" (startup)`,
|
||||
`Issue on initial workflow activation try "${workflowData.name}" (startup)`,
|
||||
{
|
||||
workflowName: workflowData.name,
|
||||
workflowId: workflowData.id,
|
||||
@@ -148,21 +149,18 @@ export class ActiveWorkflowRunner {
|
||||
}
|
||||
Logger.verbose('Finished initializing active workflows (startup)');
|
||||
}
|
||||
const externalHooks = ExternalHooks();
|
||||
await externalHooks.run('activeWorkflows.initialized', []);
|
||||
|
||||
await this.externalHooks.run('activeWorkflows.initialized', []);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes all the currently active workflows
|
||||
*
|
||||
*/
|
||||
async removeAll(): Promise<void> {
|
||||
let activeWorkflowIds: string[] = [];
|
||||
Logger.verbose('Call to remove all active workflows received (removeAll)');
|
||||
|
||||
if (this.activeWorkflows !== null) {
|
||||
activeWorkflowIds.push.apply(activeWorkflowIds, this.activeWorkflows.allActiveWorkflows());
|
||||
}
|
||||
activeWorkflowIds.push.apply(activeWorkflowIds, this.activeWorkflows.allActiveWorkflows());
|
||||
|
||||
const activeWorkflows = await this.getActiveWorkflows();
|
||||
activeWorkflowIds = [
|
||||
@@ -183,7 +181,6 @@ export class ActiveWorkflowRunner {
|
||||
|
||||
/**
|
||||
* Checks if a webhook for the given method and path exists and executes the workflow.
|
||||
*
|
||||
*/
|
||||
async executeWebhook(
|
||||
httpMethod: WebhookHttpMethod,
|
||||
@@ -192,11 +189,6 @@ export class ActiveWorkflowRunner {
|
||||
res: express.Response,
|
||||
): Promise<IResponseCallbackData> {
|
||||
Logger.debug(`Received webhook "${httpMethod}" for path "${path}"`);
|
||||
if (this.activeWorkflows === null) {
|
||||
throw new ResponseHelper.NotFoundError(
|
||||
'The "activeWorkflows" instance did not get initialized yet.',
|
||||
);
|
||||
}
|
||||
|
||||
// Reset request parameters
|
||||
req.params = {};
|
||||
@@ -279,7 +271,7 @@ export class ActiveWorkflowRunner {
|
||||
);
|
||||
}
|
||||
|
||||
const nodeTypes = NodeTypes();
|
||||
const nodeTypes = Container.get(NodeTypes);
|
||||
const workflow = new Workflow({
|
||||
id: webhook.workflowId,
|
||||
name: workflowData.name,
|
||||
@@ -482,6 +474,7 @@ export class ActiveWorkflowRunner {
|
||||
try {
|
||||
await this.removeWorkflowWebhooks(workflow.id as string);
|
||||
} catch (error) {
|
||||
ErrorReporter.error(error);
|
||||
Logger.error(
|
||||
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
|
||||
`Could not remove webhooks of workflow "${workflow.id}" because of error: "${error.message}"`,
|
||||
@@ -521,7 +514,7 @@ export class ActiveWorkflowRunner {
|
||||
throw new Error(`Could not find workflow with id "${workflowId}"`);
|
||||
}
|
||||
|
||||
const nodeTypes = NodeTypes();
|
||||
const nodeTypes = Container.get(NodeTypes);
|
||||
const workflow = new Workflow({
|
||||
id: workflowId,
|
||||
name: workflowData.name,
|
||||
@@ -645,7 +638,7 @@ export class ActiveWorkflowRunner {
|
||||
|
||||
if (donePromise) {
|
||||
executePromise.then((executionId) => {
|
||||
ActiveExecutions.getInstance()
|
||||
Container.get(ActiveExecutions)
|
||||
.getPostExecutePromise(executionId)
|
||||
.then(donePromise.resolve)
|
||||
.catch(donePromise.reject);
|
||||
@@ -702,7 +695,7 @@ export class ActiveWorkflowRunner {
|
||||
|
||||
if (donePromise) {
|
||||
executePromise.then((executionId) => {
|
||||
ActiveExecutions.getInstance()
|
||||
Container.get(ActiveExecutions)
|
||||
.getPostExecutePromise(executionId)
|
||||
.then(donePromise.resolve)
|
||||
.catch(donePromise.reject);
|
||||
@@ -723,7 +716,7 @@ export class ActiveWorkflowRunner {
|
||||
|
||||
// Remove the workflow as "active"
|
||||
|
||||
await this.activeWorkflows?.remove(workflowData.id);
|
||||
await this.activeWorkflows.remove(workflowData.id);
|
||||
this.activationErrors[workflowData.id] = {
|
||||
time: new Date().getTime(),
|
||||
error: {
|
||||
@@ -777,10 +770,6 @@ export class ActiveWorkflowRunner {
|
||||
activation: WorkflowActivateMode,
|
||||
workflowData?: IWorkflowDb,
|
||||
): Promise<void> {
|
||||
if (this.activeWorkflows === null) {
|
||||
throw new Error('The "activeWorkflows" instance did not get initialized yet.');
|
||||
}
|
||||
|
||||
let workflowInstance: Workflow;
|
||||
try {
|
||||
if (workflowData === undefined) {
|
||||
@@ -793,7 +782,7 @@ export class ActiveWorkflowRunner {
|
||||
if (!workflowData) {
|
||||
throw new Error(`Could not find workflow with id "${workflowId}".`);
|
||||
}
|
||||
const nodeTypes = NodeTypes();
|
||||
const nodeTypes = Container.get(NodeTypes);
|
||||
workflowInstance = new Workflow({
|
||||
id: workflowId,
|
||||
name: workflowData.name,
|
||||
@@ -978,47 +967,31 @@ export class ActiveWorkflowRunner {
|
||||
*/
|
||||
// TODO: this should happen in a transaction
|
||||
async remove(workflowId: string): Promise<void> {
|
||||
if (this.activeWorkflows !== null) {
|
||||
// Remove all the webhooks of the workflow
|
||||
try {
|
||||
await this.removeWorkflowWebhooks(workflowId);
|
||||
} catch (error) {
|
||||
ErrorReporter.error(error);
|
||||
Logger.error(
|
||||
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
|
||||
`Could not remove webhooks of workflow "${workflowId}" because of error: "${error.message}"`,
|
||||
);
|
||||
}
|
||||
|
||||
if (this.activationErrors[workflowId] !== undefined) {
|
||||
// If there were any activation errors delete them
|
||||
delete this.activationErrors[workflowId];
|
||||
}
|
||||
|
||||
if (this.queuedWorkflowActivations[workflowId] !== undefined) {
|
||||
this.removeQueuedWorkflowActivation(workflowId);
|
||||
}
|
||||
|
||||
// if it's active in memory then it's a trigger
|
||||
// so remove from list of actives workflows
|
||||
if (this.activeWorkflows.isActive(workflowId)) {
|
||||
await this.activeWorkflows.remove(workflowId);
|
||||
Logger.verbose(`Successfully deactivated workflow "${workflowId}"`, { workflowId });
|
||||
}
|
||||
|
||||
return;
|
||||
// Remove all the webhooks of the workflow
|
||||
try {
|
||||
await this.removeWorkflowWebhooks(workflowId);
|
||||
} catch (error) {
|
||||
ErrorReporter.error(error);
|
||||
Logger.error(
|
||||
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
|
||||
`Could not remove webhooks of workflow "${workflowId}" because of error: "${error.message}"`,
|
||||
);
|
||||
}
|
||||
|
||||
throw new Error('The "activeWorkflows" instance did not get initialized yet.');
|
||||
if (this.activationErrors[workflowId] !== undefined) {
|
||||
// If there were any activation errors delete them
|
||||
delete this.activationErrors[workflowId];
|
||||
}
|
||||
|
||||
if (this.queuedWorkflowActivations[workflowId] !== undefined) {
|
||||
this.removeQueuedWorkflowActivation(workflowId);
|
||||
}
|
||||
|
||||
// if it's active in memory then it's a trigger
|
||||
// so remove from list of actives workflows
|
||||
if (this.activeWorkflows.isActive(workflowId)) {
|
||||
await this.activeWorkflows.remove(workflowId);
|
||||
Logger.verbose(`Successfully deactivated workflow "${workflowId}"`, { workflowId });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let workflowRunnerInstance: ActiveWorkflowRunner | undefined;
|
||||
|
||||
export function getInstance(): ActiveWorkflowRunner {
|
||||
if (workflowRunnerInstance === undefined) {
|
||||
workflowRunnerInstance = new ActiveWorkflowRunner();
|
||||
}
|
||||
|
||||
return workflowRunnerInstance;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user