mirror of
https://github.com/Abdulazizzn/n8n-enterprise-unlocked.git
synced 2025-12-18 10:31:15 +00:00
refactor(core): Continue porting legacy schema (#16318)
This commit is contained in:
7
packages/@n8n/config/src/configs/deployment.config.ts
Normal file
7
packages/@n8n/config/src/configs/deployment.config.ts
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
import { Config, Env } from '../decorators';
|
||||||
|
|
||||||
|
@Config
|
||||||
|
export class DeploymentConfig {
|
||||||
|
@Env('N8N_DEPLOYMENT_TYPE')
|
||||||
|
type: string = 'default';
|
||||||
|
}
|
||||||
8
packages/@n8n/config/src/configs/hiring-banner.config.ts
Normal file
8
packages/@n8n/config/src/configs/hiring-banner.config.ts
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
import { Config, Env } from '../decorators';
|
||||||
|
|
||||||
|
@Config
|
||||||
|
export class HiringBannerConfig {
|
||||||
|
/** Whether hiring banner in browser console is enabled. */
|
||||||
|
@Env('N8N_HIRING_BANNER_ENABLED')
|
||||||
|
enabled: boolean = true;
|
||||||
|
}
|
||||||
8
packages/@n8n/config/src/configs/mfa.config.ts
Normal file
8
packages/@n8n/config/src/configs/mfa.config.ts
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
import { Config, Env } from '../decorators';
|
||||||
|
|
||||||
|
@Config
|
||||||
|
export class MfaConfig {
|
||||||
|
/** Whether to enable multi-factor authentication. */
|
||||||
|
@Env('N8N_MFA_ENABLED')
|
||||||
|
enabled: boolean = true;
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
import { Config, Env } from '../decorators';
|
||||||
|
|
||||||
|
@Config
|
||||||
|
export class PersonalizationConfig {
|
||||||
|
@Env('N8N_PERSONALIZATION_ENABLED')
|
||||||
|
enabled: boolean = true;
|
||||||
|
}
|
||||||
@@ -5,17 +5,21 @@ import { AuthConfig } from './configs/auth.config';
|
|||||||
import { CacheConfig } from './configs/cache.config';
|
import { CacheConfig } from './configs/cache.config';
|
||||||
import { CredentialsConfig } from './configs/credentials.config';
|
import { CredentialsConfig } from './configs/credentials.config';
|
||||||
import { DatabaseConfig } from './configs/database.config';
|
import { DatabaseConfig } from './configs/database.config';
|
||||||
|
import { DeploymentConfig } from './configs/deployment.config';
|
||||||
import { DiagnosticsConfig } from './configs/diagnostics.config';
|
import { DiagnosticsConfig } from './configs/diagnostics.config';
|
||||||
import { EndpointsConfig } from './configs/endpoints.config';
|
import { EndpointsConfig } from './configs/endpoints.config';
|
||||||
import { EventBusConfig } from './configs/event-bus.config';
|
import { EventBusConfig } from './configs/event-bus.config';
|
||||||
import { ExecutionsConfig } from './configs/executions.config';
|
import { ExecutionsConfig } from './configs/executions.config';
|
||||||
import { ExternalHooksConfig } from './configs/external-hooks.config';
|
import { ExternalHooksConfig } from './configs/external-hooks.config';
|
||||||
import { GenericConfig } from './configs/generic.config';
|
import { GenericConfig } from './configs/generic.config';
|
||||||
|
import { HiringBannerConfig } from './configs/hiring-banner.config';
|
||||||
import { LicenseConfig } from './configs/license.config';
|
import { LicenseConfig } from './configs/license.config';
|
||||||
import { LoggingConfig } from './configs/logging.config';
|
import { LoggingConfig } from './configs/logging.config';
|
||||||
|
import { MfaConfig } from './configs/mfa.config';
|
||||||
import { MultiMainSetupConfig } from './configs/multi-main-setup.config';
|
import { MultiMainSetupConfig } from './configs/multi-main-setup.config';
|
||||||
import { NodesConfig } from './configs/nodes.config';
|
import { NodesConfig } from './configs/nodes.config';
|
||||||
import { PartialExecutionsConfig } from './configs/partial-executions.config';
|
import { PartialExecutionsConfig } from './configs/partial-executions.config';
|
||||||
|
import { PersonalizationConfig } from './configs/personalization.config';
|
||||||
import { PublicApiConfig } from './configs/public-api.config';
|
import { PublicApiConfig } from './configs/public-api.config';
|
||||||
import { TaskRunnersConfig } from './configs/runners.config';
|
import { TaskRunnersConfig } from './configs/runners.config';
|
||||||
import { ScalingModeConfig } from './configs/scaling-mode.config';
|
import { ScalingModeConfig } from './configs/scaling-mode.config';
|
||||||
@@ -39,6 +43,10 @@ export { LOG_SCOPES } from './configs/logging.config';
|
|||||||
export type { LogScope } from './configs/logging.config';
|
export type { LogScope } from './configs/logging.config';
|
||||||
export { WorkflowsConfig } from './configs/workflows.config';
|
export { WorkflowsConfig } from './configs/workflows.config';
|
||||||
export * from './custom-types';
|
export * from './custom-types';
|
||||||
|
export { DeploymentConfig } from './configs/deployment.config';
|
||||||
|
export { MfaConfig } from './configs/mfa.config';
|
||||||
|
export { HiringBannerConfig } from './configs/hiring-banner.config';
|
||||||
|
export { PersonalizationConfig } from './configs/personalization.config';
|
||||||
|
|
||||||
const protocolSchema = z.enum(['http', 'https']);
|
const protocolSchema = z.enum(['http', 'https']);
|
||||||
|
|
||||||
@@ -146,4 +154,28 @@ export class GlobalConfig {
|
|||||||
|
|
||||||
@Nested
|
@Nested
|
||||||
workflowHistory: WorkflowHistoryConfig;
|
workflowHistory: WorkflowHistoryConfig;
|
||||||
|
|
||||||
|
@Nested
|
||||||
|
deployment: DeploymentConfig;
|
||||||
|
|
||||||
|
@Nested
|
||||||
|
mfa: MfaConfig;
|
||||||
|
|
||||||
|
@Nested
|
||||||
|
hiringBanner: HiringBannerConfig;
|
||||||
|
|
||||||
|
@Nested
|
||||||
|
personalization: PersonalizationConfig;
|
||||||
|
|
||||||
|
/** Default locale for the UI. */
|
||||||
|
@Env('N8N_DEFAULT_LOCALE')
|
||||||
|
defaultLocale: string = 'en';
|
||||||
|
|
||||||
|
/** Whether to hide the page that shows active workflows and executions count. */
|
||||||
|
@Env('N8N_HIDE_USAGE_PAGE')
|
||||||
|
hideUsagePage: boolean = false;
|
||||||
|
|
||||||
|
/** Number of reverse proxies n8n is running behind. */
|
||||||
|
@Env('N8N_PROXY_HOPS')
|
||||||
|
proxy_hops: number = 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,6 +33,21 @@ describe('GlobalConfig', () => {
|
|||||||
secure: true,
|
secure: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
defaultLocale: 'en',
|
||||||
|
hideUsagePage: false,
|
||||||
|
deployment: {
|
||||||
|
type: 'default',
|
||||||
|
},
|
||||||
|
mfa: {
|
||||||
|
enabled: true,
|
||||||
|
},
|
||||||
|
hiringBanner: {
|
||||||
|
enabled: true,
|
||||||
|
},
|
||||||
|
personalization: {
|
||||||
|
enabled: true,
|
||||||
|
},
|
||||||
|
proxy_hops: 0,
|
||||||
database: {
|
database: {
|
||||||
logging: {
|
logging: {
|
||||||
enabled: false,
|
enabled: false,
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ export abstract class AbstractServer {
|
|||||||
this.app.set('view engine', 'handlebars');
|
this.app.set('view engine', 'handlebars');
|
||||||
this.app.set('views', TEMPLATES_DIR);
|
this.app.set('views', TEMPLATES_DIR);
|
||||||
|
|
||||||
const proxyHops = config.getEnv('proxy_hops');
|
const proxyHops = this.globalConfig.proxy_hops;
|
||||||
if (proxyHops > 0) this.app.set('trust proxy', proxyHops);
|
if (proxyHops > 0) this.app.set('trust proxy', proxyHops);
|
||||||
|
|
||||||
this.sslKey = config.getEnv('ssl_key');
|
this.sslKey = config.getEnv('ssl_key');
|
||||||
@@ -260,7 +260,7 @@ export abstract class AbstractServer {
|
|||||||
if (!inTest) {
|
if (!inTest) {
|
||||||
this.logger.info(`Version: ${N8N_VERSION}`);
|
this.logger.info(`Version: ${N8N_VERSION}`);
|
||||||
|
|
||||||
const defaultLocale = config.getEnv('defaultLocale');
|
const { defaultLocale } = this.globalConfig;
|
||||||
if (defaultLocale !== 'en') {
|
if (defaultLocale !== 'en') {
|
||||||
this.logger.info(`Locale: ${defaultLocale}`);
|
this.logger.info(`Locale: ${defaultLocale}`);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import type { GlobalConfig } from '@n8n/config';
|
||||||
import type { ExecutionRepository } from '@n8n/db';
|
import type { ExecutionRepository } from '@n8n/db';
|
||||||
import { mock } from 'jest-mock-extended';
|
import { mock } from 'jest-mock-extended';
|
||||||
import type { WorkflowExecuteMode as ExecutionMode } from 'n8n-workflow';
|
import type { WorkflowExecuteMode as ExecutionMode } from 'n8n-workflow';
|
||||||
@@ -21,6 +22,7 @@ describe('ConcurrencyControlService', () => {
|
|||||||
const executionRepository = mock<ExecutionRepository>();
|
const executionRepository = mock<ExecutionRepository>();
|
||||||
const telemetry = mock<Telemetry>();
|
const telemetry = mock<Telemetry>();
|
||||||
const eventService = mock<EventService>();
|
const eventService = mock<EventService>();
|
||||||
|
const globalConfig = mock<GlobalConfig>();
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
config.set('executions.concurrency.productionLimit', -1);
|
config.set('executions.concurrency.productionLimit', -1);
|
||||||
@@ -47,6 +49,7 @@ describe('ConcurrencyControlService', () => {
|
|||||||
executionRepository,
|
executionRepository,
|
||||||
telemetry,
|
telemetry,
|
||||||
eventService,
|
eventService,
|
||||||
|
globalConfig,
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -73,7 +76,13 @@ describe('ConcurrencyControlService', () => {
|
|||||||
/**
|
/**
|
||||||
* Act
|
* Act
|
||||||
*/
|
*/
|
||||||
new ConcurrencyControlService(logger, executionRepository, telemetry, eventService);
|
new ConcurrencyControlService(
|
||||||
|
logger,
|
||||||
|
executionRepository,
|
||||||
|
telemetry,
|
||||||
|
eventService,
|
||||||
|
globalConfig,
|
||||||
|
);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
/**
|
/**
|
||||||
* Assert
|
* Assert
|
||||||
@@ -98,6 +107,7 @@ describe('ConcurrencyControlService', () => {
|
|||||||
executionRepository,
|
executionRepository,
|
||||||
telemetry,
|
telemetry,
|
||||||
eventService,
|
eventService,
|
||||||
|
globalConfig,
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -123,6 +133,7 @@ describe('ConcurrencyControlService', () => {
|
|||||||
executionRepository,
|
executionRepository,
|
||||||
telemetry,
|
telemetry,
|
||||||
eventService,
|
eventService,
|
||||||
|
globalConfig,
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -148,6 +159,7 @@ describe('ConcurrencyControlService', () => {
|
|||||||
executionRepository,
|
executionRepository,
|
||||||
telemetry,
|
telemetry,
|
||||||
eventService,
|
eventService,
|
||||||
|
globalConfig,
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -177,6 +189,7 @@ describe('ConcurrencyControlService', () => {
|
|||||||
executionRepository,
|
executionRepository,
|
||||||
telemetry,
|
telemetry,
|
||||||
eventService,
|
eventService,
|
||||||
|
globalConfig,
|
||||||
);
|
);
|
||||||
const enqueueSpy = jest.spyOn(ConcurrencyQueue.prototype, 'enqueue');
|
const enqueueSpy = jest.spyOn(ConcurrencyQueue.prototype, 'enqueue');
|
||||||
|
|
||||||
@@ -203,6 +216,7 @@ describe('ConcurrencyControlService', () => {
|
|||||||
executionRepository,
|
executionRepository,
|
||||||
telemetry,
|
telemetry,
|
||||||
eventService,
|
eventService,
|
||||||
|
globalConfig,
|
||||||
);
|
);
|
||||||
const enqueueSpy = jest.spyOn(ConcurrencyQueue.prototype, 'enqueue');
|
const enqueueSpy = jest.spyOn(ConcurrencyQueue.prototype, 'enqueue');
|
||||||
|
|
||||||
@@ -228,6 +242,7 @@ describe('ConcurrencyControlService', () => {
|
|||||||
executionRepository,
|
executionRepository,
|
||||||
telemetry,
|
telemetry,
|
||||||
eventService,
|
eventService,
|
||||||
|
globalConfig,
|
||||||
);
|
);
|
||||||
const enqueueSpy = jest.spyOn(ConcurrencyQueue.prototype, 'enqueue');
|
const enqueueSpy = jest.spyOn(ConcurrencyQueue.prototype, 'enqueue');
|
||||||
|
|
||||||
@@ -257,6 +272,7 @@ describe('ConcurrencyControlService', () => {
|
|||||||
executionRepository,
|
executionRepository,
|
||||||
telemetry,
|
telemetry,
|
||||||
eventService,
|
eventService,
|
||||||
|
globalConfig,
|
||||||
);
|
);
|
||||||
const dequeueSpy = jest.spyOn(ConcurrencyQueue.prototype, 'dequeue');
|
const dequeueSpy = jest.spyOn(ConcurrencyQueue.prototype, 'dequeue');
|
||||||
|
|
||||||
@@ -283,6 +299,7 @@ describe('ConcurrencyControlService', () => {
|
|||||||
executionRepository,
|
executionRepository,
|
||||||
telemetry,
|
telemetry,
|
||||||
eventService,
|
eventService,
|
||||||
|
globalConfig,
|
||||||
);
|
);
|
||||||
const dequeueSpy = jest.spyOn(ConcurrencyQueue.prototype, 'dequeue');
|
const dequeueSpy = jest.spyOn(ConcurrencyQueue.prototype, 'dequeue');
|
||||||
|
|
||||||
@@ -308,6 +325,7 @@ describe('ConcurrencyControlService', () => {
|
|||||||
executionRepository,
|
executionRepository,
|
||||||
telemetry,
|
telemetry,
|
||||||
eventService,
|
eventService,
|
||||||
|
globalConfig,
|
||||||
);
|
);
|
||||||
const dequeueSpy = jest.spyOn(ConcurrencyQueue.prototype, 'dequeue');
|
const dequeueSpy = jest.spyOn(ConcurrencyQueue.prototype, 'dequeue');
|
||||||
|
|
||||||
@@ -337,6 +355,7 @@ describe('ConcurrencyControlService', () => {
|
|||||||
executionRepository,
|
executionRepository,
|
||||||
telemetry,
|
telemetry,
|
||||||
eventService,
|
eventService,
|
||||||
|
globalConfig,
|
||||||
);
|
);
|
||||||
const removeSpy = jest.spyOn(ConcurrencyQueue.prototype, 'remove');
|
const removeSpy = jest.spyOn(ConcurrencyQueue.prototype, 'remove');
|
||||||
|
|
||||||
@@ -365,6 +384,7 @@ describe('ConcurrencyControlService', () => {
|
|||||||
executionRepository,
|
executionRepository,
|
||||||
telemetry,
|
telemetry,
|
||||||
eventService,
|
eventService,
|
||||||
|
globalConfig,
|
||||||
);
|
);
|
||||||
const removeSpy = jest.spyOn(ConcurrencyQueue.prototype, 'remove');
|
const removeSpy = jest.spyOn(ConcurrencyQueue.prototype, 'remove');
|
||||||
|
|
||||||
@@ -391,6 +411,7 @@ describe('ConcurrencyControlService', () => {
|
|||||||
executionRepository,
|
executionRepository,
|
||||||
telemetry,
|
telemetry,
|
||||||
eventService,
|
eventService,
|
||||||
|
globalConfig,
|
||||||
);
|
);
|
||||||
const removeSpy = jest.spyOn(ConcurrencyQueue.prototype, 'remove');
|
const removeSpy = jest.spyOn(ConcurrencyQueue.prototype, 'remove');
|
||||||
|
|
||||||
@@ -420,6 +441,7 @@ describe('ConcurrencyControlService', () => {
|
|||||||
executionRepository,
|
executionRepository,
|
||||||
telemetry,
|
telemetry,
|
||||||
eventService,
|
eventService,
|
||||||
|
globalConfig,
|
||||||
);
|
);
|
||||||
|
|
||||||
jest
|
jest
|
||||||
@@ -459,6 +481,7 @@ describe('ConcurrencyControlService', () => {
|
|||||||
executionRepository,
|
executionRepository,
|
||||||
telemetry,
|
telemetry,
|
||||||
eventService,
|
eventService,
|
||||||
|
globalConfig,
|
||||||
);
|
);
|
||||||
// @ts-expect-error Private property
|
// @ts-expect-error Private property
|
||||||
const queue = service.getQueue('webhook');
|
const queue = service.getQueue('webhook');
|
||||||
@@ -485,6 +508,7 @@ describe('ConcurrencyControlService', () => {
|
|||||||
executionRepository,
|
executionRepository,
|
||||||
telemetry,
|
telemetry,
|
||||||
eventService,
|
eventService,
|
||||||
|
globalConfig,
|
||||||
);
|
);
|
||||||
// @ts-expect-error Private property
|
// @ts-expect-error Private property
|
||||||
const queue = service.getQueue('evaluation');
|
const queue = service.getQueue('evaluation');
|
||||||
@@ -515,6 +539,7 @@ describe('ConcurrencyControlService', () => {
|
|||||||
executionRepository,
|
executionRepository,
|
||||||
telemetry,
|
telemetry,
|
||||||
eventService,
|
eventService,
|
||||||
|
globalConfig,
|
||||||
);
|
);
|
||||||
const enqueueSpy = jest.spyOn(ConcurrencyQueue.prototype, 'enqueue');
|
const enqueueSpy = jest.spyOn(ConcurrencyQueue.prototype, 'enqueue');
|
||||||
|
|
||||||
@@ -541,6 +566,7 @@ describe('ConcurrencyControlService', () => {
|
|||||||
executionRepository,
|
executionRepository,
|
||||||
telemetry,
|
telemetry,
|
||||||
eventService,
|
eventService,
|
||||||
|
globalConfig,
|
||||||
);
|
);
|
||||||
const enqueueSpy = jest.spyOn(ConcurrencyQueue.prototype, 'enqueue');
|
const enqueueSpy = jest.spyOn(ConcurrencyQueue.prototype, 'enqueue');
|
||||||
|
|
||||||
@@ -569,6 +595,7 @@ describe('ConcurrencyControlService', () => {
|
|||||||
executionRepository,
|
executionRepository,
|
||||||
telemetry,
|
telemetry,
|
||||||
eventService,
|
eventService,
|
||||||
|
globalConfig,
|
||||||
);
|
);
|
||||||
const dequeueSpy = jest.spyOn(ConcurrencyQueue.prototype, 'dequeue');
|
const dequeueSpy = jest.spyOn(ConcurrencyQueue.prototype, 'dequeue');
|
||||||
|
|
||||||
@@ -594,6 +621,7 @@ describe('ConcurrencyControlService', () => {
|
|||||||
executionRepository,
|
executionRepository,
|
||||||
telemetry,
|
telemetry,
|
||||||
eventService,
|
eventService,
|
||||||
|
globalConfig,
|
||||||
);
|
);
|
||||||
const dequeueSpy = jest.spyOn(ConcurrencyQueue.prototype, 'dequeue');
|
const dequeueSpy = jest.spyOn(ConcurrencyQueue.prototype, 'dequeue');
|
||||||
|
|
||||||
@@ -621,6 +649,7 @@ describe('ConcurrencyControlService', () => {
|
|||||||
executionRepository,
|
executionRepository,
|
||||||
telemetry,
|
telemetry,
|
||||||
eventService,
|
eventService,
|
||||||
|
globalConfig,
|
||||||
);
|
);
|
||||||
const removeSpy = jest.spyOn(ConcurrencyQueue.prototype, 'remove');
|
const removeSpy = jest.spyOn(ConcurrencyQueue.prototype, 'remove');
|
||||||
|
|
||||||
@@ -646,6 +675,7 @@ describe('ConcurrencyControlService', () => {
|
|||||||
executionRepository,
|
executionRepository,
|
||||||
telemetry,
|
telemetry,
|
||||||
eventService,
|
eventService,
|
||||||
|
globalConfig,
|
||||||
);
|
);
|
||||||
const removeSpy = jest.spyOn(ConcurrencyQueue.prototype, 'remove');
|
const removeSpy = jest.spyOn(ConcurrencyQueue.prototype, 'remove');
|
||||||
|
|
||||||
@@ -675,12 +705,13 @@ describe('ConcurrencyControlService', () => {
|
|||||||
* Arrange
|
* Arrange
|
||||||
*/
|
*/
|
||||||
config.set('executions.concurrency.productionLimit', CLOUD_TEMP_PRODUCTION_LIMIT);
|
config.set('executions.concurrency.productionLimit', CLOUD_TEMP_PRODUCTION_LIMIT);
|
||||||
config.set('deployment.type', 'cloud');
|
globalConfig.deployment.type = 'cloud';
|
||||||
const service = new ConcurrencyControlService(
|
const service = new ConcurrencyControlService(
|
||||||
logger,
|
logger,
|
||||||
executionRepository,
|
executionRepository,
|
||||||
telemetry,
|
telemetry,
|
||||||
eventService,
|
eventService,
|
||||||
|
globalConfig,
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -708,12 +739,13 @@ describe('ConcurrencyControlService', () => {
|
|||||||
* Arrange
|
* Arrange
|
||||||
*/
|
*/
|
||||||
config.set('executions.concurrency.productionLimit', CLOUD_TEMP_PRODUCTION_LIMIT);
|
config.set('executions.concurrency.productionLimit', CLOUD_TEMP_PRODUCTION_LIMIT);
|
||||||
config.set('deployment.type', 'cloud');
|
globalConfig.deployment.type = 'cloud';
|
||||||
const service = new ConcurrencyControlService(
|
const service = new ConcurrencyControlService(
|
||||||
logger,
|
logger,
|
||||||
executionRepository,
|
executionRepository,
|
||||||
telemetry,
|
telemetry,
|
||||||
eventService,
|
eventService,
|
||||||
|
globalConfig,
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -740,12 +772,13 @@ describe('ConcurrencyControlService', () => {
|
|||||||
* Arrange
|
* Arrange
|
||||||
*/
|
*/
|
||||||
config.set('executions.concurrency.productionLimit', CLOUD_TEMP_PRODUCTION_LIMIT);
|
config.set('executions.concurrency.productionLimit', CLOUD_TEMP_PRODUCTION_LIMIT);
|
||||||
config.set('deployment.type', 'cloud');
|
globalConfig.deployment.type = 'cloud';
|
||||||
const service = new ConcurrencyControlService(
|
const service = new ConcurrencyControlService(
|
||||||
logger,
|
logger,
|
||||||
executionRepository,
|
executionRepository,
|
||||||
telemetry,
|
telemetry,
|
||||||
eventService,
|
eventService,
|
||||||
|
globalConfig,
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { Logger } from '@n8n/backend-common';
|
import { Logger } from '@n8n/backend-common';
|
||||||
|
import { GlobalConfig } from '@n8n/config';
|
||||||
import { ExecutionRepository } from '@n8n/db';
|
import { ExecutionRepository } from '@n8n/db';
|
||||||
import { Service } from '@n8n/di';
|
import { Service } from '@n8n/di';
|
||||||
import capitalize from 'lodash/capitalize';
|
import capitalize from 'lodash/capitalize';
|
||||||
@@ -34,6 +35,7 @@ export class ConcurrencyControlService {
|
|||||||
private readonly executionRepository: ExecutionRepository,
|
private readonly executionRepository: ExecutionRepository,
|
||||||
private readonly telemetry: Telemetry,
|
private readonly telemetry: Telemetry,
|
||||||
private readonly eventService: EventService,
|
private readonly eventService: EventService,
|
||||||
|
private readonly globalConfig: GlobalConfig,
|
||||||
) {
|
) {
|
||||||
this.logger = this.logger.scoped('concurrency');
|
this.logger = this.logger.scoped('concurrency');
|
||||||
|
|
||||||
@@ -185,7 +187,7 @@ export class ConcurrencyControlService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private shouldReport(capacity: number) {
|
private shouldReport(capacity: number) {
|
||||||
return config.getEnv('deployment.type') === 'cloud' && this.limitsToReport.includes(capacity);
|
return this.globalConfig.deployment.type === 'cloud' && this.limitsToReport.includes(capacity);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -165,23 +165,6 @@ export const schema = {
|
|||||||
env: 'EXTERNAL_FRONTEND_HOOKS_URLS',
|
env: 'EXTERNAL_FRONTEND_HOOKS_URLS',
|
||||||
},
|
},
|
||||||
|
|
||||||
deployment: {
|
|
||||||
type: {
|
|
||||||
format: String,
|
|
||||||
default: 'default',
|
|
||||||
env: 'N8N_DEPLOYMENT_TYPE',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
mfa: {
|
|
||||||
enabled: {
|
|
||||||
format: Boolean,
|
|
||||||
default: true,
|
|
||||||
doc: 'Whether to enable MFA feature in instance.',
|
|
||||||
env: 'N8N_MFA_ENABLED',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
sso: {
|
sso: {
|
||||||
justInTimeProvisioning: {
|
justInTimeProvisioning: {
|
||||||
format: Boolean,
|
format: Boolean,
|
||||||
@@ -223,38 +206,6 @@ export const schema = {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
hiringBanner: {
|
|
||||||
enabled: {
|
|
||||||
doc: 'Whether hiring banner in browser console is enabled.',
|
|
||||||
format: Boolean,
|
|
||||||
default: true,
|
|
||||||
env: 'N8N_HIRING_BANNER_ENABLED',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
personalization: {
|
|
||||||
enabled: {
|
|
||||||
doc: 'Whether personalization is enabled.',
|
|
||||||
format: Boolean,
|
|
||||||
default: true,
|
|
||||||
env: 'N8N_PERSONALIZATION_ENABLED',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
defaultLocale: {
|
|
||||||
doc: 'Default locale for the UI',
|
|
||||||
format: String,
|
|
||||||
default: 'en',
|
|
||||||
env: 'N8N_DEFAULT_LOCALE',
|
|
||||||
},
|
|
||||||
|
|
||||||
hideUsagePage: {
|
|
||||||
format: Boolean,
|
|
||||||
default: false,
|
|
||||||
env: 'N8N_HIDE_USAGE_PAGE',
|
|
||||||
doc: 'Hide or show the usage page',
|
|
||||||
},
|
|
||||||
|
|
||||||
redis: {
|
redis: {
|
||||||
prefix: {
|
prefix: {
|
||||||
doc: 'Prefix for all n8n related keys',
|
doc: 'Prefix for all n8n related keys',
|
||||||
@@ -285,11 +236,4 @@ export const schema = {
|
|||||||
env: 'N8N_AI_ENABLED',
|
env: 'N8N_AI_ENABLED',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
proxy_hops: {
|
|
||||||
format: Number,
|
|
||||||
default: 0,
|
|
||||||
env: 'N8N_PROXY_HOPS',
|
|
||||||
doc: 'Number of reverse-proxies n8n is running behind',
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
|
import type { GlobalConfig } from '@n8n/config';
|
||||||
import { mock } from 'jest-mock-extended';
|
import { mock } from 'jest-mock-extended';
|
||||||
|
|
||||||
import config from '@/config';
|
|
||||||
import type { TranslationRequest } from '@/controllers/translation.controller';
|
import type { TranslationRequest } from '@/controllers/translation.controller';
|
||||||
import {
|
import {
|
||||||
TranslationController,
|
TranslationController,
|
||||||
@@ -10,9 +10,11 @@ import type { CredentialTypes } from '@/credential-types';
|
|||||||
import { BadRequestError } from '@/errors/response-errors/bad-request.error';
|
import { BadRequestError } from '@/errors/response-errors/bad-request.error';
|
||||||
|
|
||||||
describe('TranslationController', () => {
|
describe('TranslationController', () => {
|
||||||
const configGetSpy = jest.spyOn(config, 'getEnv');
|
|
||||||
const credentialTypes = mock<CredentialTypes>();
|
const credentialTypes = mock<CredentialTypes>();
|
||||||
const controller = new TranslationController(credentialTypes);
|
const controller = new TranslationController(
|
||||||
|
credentialTypes,
|
||||||
|
mock<GlobalConfig>({ defaultLocale: 'de' }),
|
||||||
|
);
|
||||||
|
|
||||||
describe('getCredentialTranslation', () => {
|
describe('getCredentialTranslation', () => {
|
||||||
it('should throw 400 on invalid credential types', async () => {
|
it('should throw 400 on invalid credential types', async () => {
|
||||||
@@ -28,7 +30,6 @@ describe('TranslationController', () => {
|
|||||||
it('should return translation json on valid credential types', async () => {
|
it('should return translation json on valid credential types', async () => {
|
||||||
const credentialType = 'credential-type';
|
const credentialType = 'credential-type';
|
||||||
const req = mock<TranslationRequest.Credential>({ query: { credentialType } });
|
const req = mock<TranslationRequest.Credential>({ query: { credentialType } });
|
||||||
configGetSpy.mockReturnValue('de');
|
|
||||||
credentialTypes.recognizes.calledWith(credentialType).mockReturnValue(true);
|
credentialTypes.recognizes.calledWith(credentialType).mockReturnValue(true);
|
||||||
const response = { translation: 'string' };
|
const response = { translation: 'string' };
|
||||||
jest.mock(`${CREDENTIAL_TRANSLATIONS_DIR}/de/credential-type.json`, () => response, {
|
jest.mock(`${CREDENTIAL_TRANSLATIONS_DIR}/de/credential-type.json`, () => response, {
|
||||||
|
|||||||
@@ -1,21 +1,24 @@
|
|||||||
|
import { GlobalConfig } from '@n8n/config';
|
||||||
import { Post, RestController } from '@n8n/decorators';
|
import { Post, RestController } from '@n8n/decorators';
|
||||||
import { Request } from 'express';
|
import { Request } from 'express';
|
||||||
import { readFile } from 'fs/promises';
|
import { readFile } from 'fs/promises';
|
||||||
import get from 'lodash/get';
|
import get from 'lodash/get';
|
||||||
import type { INodeTypeDescription, INodeTypeNameVersion } from 'n8n-workflow';
|
import type { INodeTypeDescription, INodeTypeNameVersion } from 'n8n-workflow';
|
||||||
|
|
||||||
import config from '@/config';
|
|
||||||
import { NodeTypes } from '@/node-types';
|
import { NodeTypes } from '@/node-types';
|
||||||
|
|
||||||
@RestController('/node-types')
|
@RestController('/node-types')
|
||||||
export class NodeTypesController {
|
export class NodeTypesController {
|
||||||
constructor(private readonly nodeTypes: NodeTypes) {}
|
constructor(
|
||||||
|
private readonly nodeTypes: NodeTypes,
|
||||||
|
private readonly globalConfig: GlobalConfig,
|
||||||
|
) {}
|
||||||
|
|
||||||
@Post('/')
|
@Post('/')
|
||||||
async getNodeInfo(req: Request) {
|
async getNodeInfo(req: Request) {
|
||||||
const nodeInfos = get(req, 'body.nodeInfos', []) as INodeTypeNameVersion[];
|
const nodeInfos = get(req, 'body.nodeInfos', []) as INodeTypeNameVersion[];
|
||||||
|
|
||||||
const defaultLocale = config.getEnv('defaultLocale');
|
const defaultLocale = this.globalConfig.defaultLocale;
|
||||||
|
|
||||||
if (defaultLocale === 'en') {
|
if (defaultLocale === 'en') {
|
||||||
return nodeInfos.reduce<INodeTypeDescription[]>((acc, { name, version }) => {
|
return nodeInfos.reduce<INodeTypeDescription[]>((acc, { name, version }) => {
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
|
import { GlobalConfig } from '@n8n/config';
|
||||||
import { Get, RestController } from '@n8n/decorators';
|
import { Get, RestController } from '@n8n/decorators';
|
||||||
import type { Request } from 'express';
|
import type { Request } from 'express';
|
||||||
import { access } from 'fs/promises';
|
import { access } from 'fs/promises';
|
||||||
import { join } from 'path';
|
import { join } from 'path';
|
||||||
|
|
||||||
import config from '@/config';
|
|
||||||
import { NODES_BASE_DIR } from '@/constants';
|
import { NODES_BASE_DIR } from '@/constants';
|
||||||
import { CredentialTypes } from '@/credential-types';
|
import { CredentialTypes } from '@/credential-types';
|
||||||
import { BadRequestError } from '@/errors/response-errors/bad-request.error';
|
import { BadRequestError } from '@/errors/response-errors/bad-request.error';
|
||||||
@@ -18,7 +18,10 @@ export declare namespace TranslationRequest {
|
|||||||
|
|
||||||
@RestController('/')
|
@RestController('/')
|
||||||
export class TranslationController {
|
export class TranslationController {
|
||||||
constructor(private readonly credentialTypes: CredentialTypes) {}
|
constructor(
|
||||||
|
private readonly credentialTypes: CredentialTypes,
|
||||||
|
private readonly globalConfig: GlobalConfig,
|
||||||
|
) {}
|
||||||
|
|
||||||
@Get('/credential-translation')
|
@Get('/credential-translation')
|
||||||
async getCredentialTranslation(req: TranslationRequest.Credential) {
|
async getCredentialTranslation(req: TranslationRequest.Credential) {
|
||||||
@@ -27,7 +30,7 @@ export class TranslationController {
|
|||||||
if (!this.credentialTypes.recognizes(credentialType))
|
if (!this.credentialTypes.recognizes(credentialType))
|
||||||
throw new BadRequestError(`Invalid Credential type: "${credentialType}"`);
|
throw new BadRequestError(`Invalid Credential type: "${credentialType}"`);
|
||||||
|
|
||||||
const defaultLocale = config.getEnv('defaultLocale');
|
const { defaultLocale } = this.globalConfig;
|
||||||
const translationPath = join(
|
const translationPath = join(
|
||||||
CREDENTIAL_TRANSLATIONS_DIR,
|
CREDENTIAL_TRANSLATIONS_DIR,
|
||||||
defaultLocale,
|
defaultLocale,
|
||||||
|
|||||||
@@ -26,6 +26,9 @@ describe('TelemetryEventRelay', () => {
|
|||||||
const telemetry = mock<Telemetry>();
|
const telemetry = mock<Telemetry>();
|
||||||
const license = mock<License>();
|
const license = mock<License>();
|
||||||
const globalConfig = mock<GlobalConfig>({
|
const globalConfig = mock<GlobalConfig>({
|
||||||
|
deployment: {
|
||||||
|
type: 'default',
|
||||||
|
},
|
||||||
userManagement: {
|
userManagement: {
|
||||||
emails: {
|
emails: {
|
||||||
mode: 'smtp',
|
mode: 'smtp',
|
||||||
|
|||||||
@@ -578,7 +578,7 @@ export class TelemetryEventRelay extends EventRelay {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private async workflowSaved({ user, workflow, publicApi }: RelayEventMap['workflow-saved']) {
|
private async workflowSaved({ user, workflow, publicApi }: RelayEventMap['workflow-saved']) {
|
||||||
const isCloudDeployment = config.getEnv('deployment.type') === 'cloud';
|
const isCloudDeployment = this.globalConfig.deployment.type === 'cloud';
|
||||||
|
|
||||||
const { nodeGraph } = TelemetryHelpers.generateNodesGraph(workflow, this.nodeTypes, {
|
const { nodeGraph } = TelemetryHelpers.generateNodesGraph(workflow, this.nodeTypes, {
|
||||||
isCloudDeployment,
|
isCloudDeployment,
|
||||||
@@ -835,7 +835,7 @@ export class TelemetryEventRelay extends EventRelay {
|
|||||||
executions_data_prune: this.globalConfig.executions.pruneData,
|
executions_data_prune: this.globalConfig.executions.pruneData,
|
||||||
executions_data_max_age: this.globalConfig.executions.pruneDataMaxAge,
|
executions_data_max_age: this.globalConfig.executions.pruneDataMaxAge,
|
||||||
},
|
},
|
||||||
n8n_deployment_type: config.getEnv('deployment.type'),
|
n8n_deployment_type: this.globalConfig.deployment.type,
|
||||||
n8n_binary_data_mode: this.binaryDataConfig.mode,
|
n8n_binary_data_mode: this.binaryDataConfig.mode,
|
||||||
smtp_set_up: this.globalConfig.userManagement.emails.mode === 'smtp',
|
smtp_set_up: this.globalConfig.userManagement.emails.mode === 'smtp',
|
||||||
ldap_allowed: authenticationMethod === 'ldap',
|
ldap_allowed: authenticationMethod === 'ldap',
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
export const MFA_FEATURE_ENABLED = 'mfa.enabled';
|
|
||||||
@@ -1,11 +1,8 @@
|
|||||||
|
import { GlobalConfig } from '@n8n/config';
|
||||||
import { UserRepository } from '@n8n/db';
|
import { UserRepository } from '@n8n/db';
|
||||||
import { Container } from '@n8n/di';
|
import { Container } from '@n8n/di';
|
||||||
|
|
||||||
import config from '@/config';
|
export const isMfaFeatureEnabled = () => Container.get(GlobalConfig).mfa.enabled;
|
||||||
|
|
||||||
import { MFA_FEATURE_ENABLED } from './constants';
|
|
||||||
|
|
||||||
export const isMfaFeatureEnabled = () => config.get(MFA_FEATURE_ENABLED);
|
|
||||||
|
|
||||||
const isMfaFeatureDisabled = () => !isMfaFeatureEnabled();
|
const isMfaFeatureDisabled = () => !isMfaFeatureEnabled();
|
||||||
|
|
||||||
@@ -18,7 +15,7 @@ export const handleMfaDisable = async () => {
|
|||||||
// users, then keep the feature enabled
|
// users, then keep the feature enabled
|
||||||
const users = await getUsersWithMfaEnabled();
|
const users = await getUsersWithMfaEnabled();
|
||||||
if (users) {
|
if (users) {
|
||||||
config.set(MFA_FEATURE_ENABLED, true);
|
Container.get(GlobalConfig).mfa.enabled = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ import axios from 'axios';
|
|||||||
import { InstanceSettings } from 'n8n-core';
|
import { InstanceSettings } from 'n8n-core';
|
||||||
import type { IWorkflowBase } from 'n8n-workflow';
|
import type { IWorkflowBase } from 'n8n-workflow';
|
||||||
|
|
||||||
import config from '@/config';
|
|
||||||
import { N8N_VERSION } from '@/constants';
|
import { N8N_VERSION } from '@/constants';
|
||||||
import { isApiEnabled } from '@/public-api';
|
import { isApiEnabled } from '@/public-api';
|
||||||
import {
|
import {
|
||||||
@@ -84,7 +83,7 @@ export class InstanceRiskReporter implements RiskReporter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private getSecuritySettings() {
|
private getSecuritySettings() {
|
||||||
if (config.getEnv('deployment.type') === 'cloud') return null;
|
if (this.globalConfig.deployment.type === 'cloud') return null;
|
||||||
|
|
||||||
const settings: Record<string, unknown> = {};
|
const settings: Record<string, unknown> = {};
|
||||||
|
|
||||||
|
|||||||
@@ -133,12 +133,12 @@ export class FrontendService {
|
|||||||
apiHost: this.globalConfig.diagnostics.posthogConfig.apiHost,
|
apiHost: this.globalConfig.diagnostics.posthogConfig.apiHost,
|
||||||
apiKey: this.globalConfig.diagnostics.posthogConfig.apiKey,
|
apiKey: this.globalConfig.diagnostics.posthogConfig.apiKey,
|
||||||
autocapture: false,
|
autocapture: false,
|
||||||
disableSessionRecording: config.getEnv('deployment.type') !== 'cloud',
|
disableSessionRecording: this.globalConfig.deployment.type !== 'cloud',
|
||||||
debug: this.globalConfig.logging.level === 'debug',
|
debug: this.globalConfig.logging.level === 'debug',
|
||||||
},
|
},
|
||||||
personalizationSurveyEnabled:
|
personalizationSurveyEnabled:
|
||||||
config.getEnv('personalization.enabled') && this.globalConfig.diagnostics.enabled,
|
this.globalConfig.personalization.enabled && this.globalConfig.diagnostics.enabled,
|
||||||
defaultLocale: config.getEnv('defaultLocale'),
|
defaultLocale: this.globalConfig.defaultLocale,
|
||||||
userManagement: {
|
userManagement: {
|
||||||
quota: this.license.getUsersLimit(),
|
quota: this.license.getUsersLimit(),
|
||||||
showSetupOnFirstLoad: !config.getEnv('userManagement.isInstanceOwnerSetUp'),
|
showSetupOnFirstLoad: !config.getEnv('userManagement.isInstanceOwnerSetUp'),
|
||||||
@@ -170,7 +170,7 @@ export class FrontendService {
|
|||||||
},
|
},
|
||||||
workflowTagsDisabled: this.globalConfig.tags.disabled,
|
workflowTagsDisabled: this.globalConfig.tags.disabled,
|
||||||
logLevel: this.globalConfig.logging.level,
|
logLevel: this.globalConfig.logging.level,
|
||||||
hiringBannerEnabled: config.getEnv('hiringBanner.enabled'),
|
hiringBannerEnabled: this.globalConfig.hiringBanner.enabled,
|
||||||
aiAssistant: {
|
aiAssistant: {
|
||||||
enabled: false,
|
enabled: false,
|
||||||
},
|
},
|
||||||
@@ -184,7 +184,7 @@ export class FrontendService {
|
|||||||
communityNodesEnabled: this.globalConfig.nodes.communityPackages.enabled,
|
communityNodesEnabled: this.globalConfig.nodes.communityPackages.enabled,
|
||||||
unverifiedCommunityNodesEnabled: this.globalConfig.nodes.communityPackages.unverifiedEnabled,
|
unverifiedCommunityNodesEnabled: this.globalConfig.nodes.communityPackages.unverifiedEnabled,
|
||||||
deployment: {
|
deployment: {
|
||||||
type: config.getEnv('deployment.type'),
|
type: this.globalConfig.deployment.type,
|
||||||
},
|
},
|
||||||
allowedModules: {
|
allowedModules: {
|
||||||
builtIn: process.env.NODE_FUNCTION_ALLOW_BUILTIN?.split(',') ?? undefined,
|
builtIn: process.env.NODE_FUNCTION_ALLOW_BUILTIN?.split(',') ?? undefined,
|
||||||
@@ -217,7 +217,7 @@ export class FrontendService {
|
|||||||
mfa: {
|
mfa: {
|
||||||
enabled: false,
|
enabled: false,
|
||||||
},
|
},
|
||||||
hideUsagePage: config.getEnv('hideUsagePage'),
|
hideUsagePage: this.globalConfig.hideUsagePage,
|
||||||
license: {
|
license: {
|
||||||
consumerId: 'unknown',
|
consumerId: 'unknown',
|
||||||
environment: this.globalConfig.license.tenantId === 1 ? 'production' : 'staging',
|
environment: this.globalConfig.license.tenantId === 1 ? 'production' : 'staging',
|
||||||
@@ -395,7 +395,7 @@ export class FrontendService {
|
|||||||
dateRanges: getInsightsAvailableDateRanges(this.licenseState),
|
dateRanges: getInsightsAvailableDateRanges(this.licenseState),
|
||||||
});
|
});
|
||||||
|
|
||||||
this.settings.mfa.enabled = config.get('mfa.enabled');
|
this.settings.mfa.enabled = this.globalConfig.mfa.enabled;
|
||||||
|
|
||||||
this.settings.executionMode = config.getEnv('executions.mode');
|
this.settings.executionMode = config.getEnv('executions.mode');
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { Service } from '@n8n/di';
|
import { GlobalConfig } from '@n8n/config';
|
||||||
|
import { Container, Service } from '@n8n/di';
|
||||||
|
|
||||||
import config from '@/config';
|
|
||||||
import type {
|
import type {
|
||||||
DisconnectAnalyzer,
|
DisconnectAnalyzer,
|
||||||
DisconnectErrorOptions,
|
DisconnectErrorOptions,
|
||||||
@@ -16,7 +16,7 @@ import { TaskRunnerFailedHeartbeatError } from './errors/task-runner-failed-hear
|
|||||||
@Service()
|
@Service()
|
||||||
export class DefaultTaskRunnerDisconnectAnalyzer implements DisconnectAnalyzer {
|
export class DefaultTaskRunnerDisconnectAnalyzer implements DisconnectAnalyzer {
|
||||||
get isCloudDeployment() {
|
get isCloudDeployment() {
|
||||||
return config.get('deployment.type') === 'cloud';
|
return Container.get(GlobalConfig).deployment.type === 'cloud';
|
||||||
}
|
}
|
||||||
|
|
||||||
async toDisconnectError(opts: DisconnectErrorOptions): Promise<Error> {
|
async toDisconnectError(opts: DisconnectErrorOptions): Promise<Error> {
|
||||||
@@ -25,7 +25,7 @@ export class DefaultTaskRunnerDisconnectAnalyzer implements DisconnectAnalyzer {
|
|||||||
if (reason === 'failed-heartbeat-check' && heartbeatInterval) {
|
if (reason === 'failed-heartbeat-check' && heartbeatInterval) {
|
||||||
return new TaskRunnerFailedHeartbeatError(
|
return new TaskRunnerFailedHeartbeatError(
|
||||||
heartbeatInterval,
|
heartbeatInterval,
|
||||||
config.get('deployment.type') !== 'cloud',
|
Container.get(GlobalConfig).deployment.type !== 'cloud',
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ describe('TaskBroker', () => {
|
|||||||
let taskBroker: TaskBroker;
|
let taskBroker: TaskBroker;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
taskBroker = new TaskBroker(mock(), mock(), mock());
|
taskBroker = new TaskBroker(mock(), mock(), mock(), mock());
|
||||||
jest.restoreAllMocks();
|
jest.restoreAllMocks();
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -724,7 +724,7 @@ describe('TaskBroker', () => {
|
|||||||
beforeAll(() => {
|
beforeAll(() => {
|
||||||
jest.useFakeTimers();
|
jest.useFakeTimers();
|
||||||
config = mock<TaskRunnersConfig>({ taskTimeout: 30, mode: 'internal' });
|
config = mock<TaskRunnersConfig>({ taskTimeout: 30, mode: 'internal' });
|
||||||
taskBroker = new TaskBroker(mock(), config, runnerLifecycleEvents);
|
taskBroker = new TaskBroker(mock(), config, runnerLifecycleEvents, mock());
|
||||||
});
|
});
|
||||||
|
|
||||||
afterAll(() => {
|
afterAll(() => {
|
||||||
@@ -844,7 +844,7 @@ describe('TaskBroker', () => {
|
|||||||
|
|
||||||
it('[external mode] on timeout, we should instruct the runner to cancel and send error to requester', async () => {
|
it('[external mode] on timeout, we should instruct the runner to cancel and send error to requester', async () => {
|
||||||
const config = mock<TaskRunnersConfig>({ taskTimeout: 30, mode: 'external' });
|
const config = mock<TaskRunnersConfig>({ taskTimeout: 30, mode: 'external' });
|
||||||
taskBroker = new TaskBroker(mock(), config, runnerLifecycleEvents);
|
taskBroker = new TaskBroker(mock(), config, runnerLifecycleEvents, mock());
|
||||||
|
|
||||||
jest.spyOn(global, 'clearTimeout');
|
jest.spyOn(global, 'clearTimeout');
|
||||||
|
|
||||||
@@ -895,7 +895,7 @@ describe('TaskBroker', () => {
|
|||||||
const messageCallback = jest.fn();
|
const messageCallback = jest.fn();
|
||||||
const loggerMock = mock<Logger>();
|
const loggerMock = mock<Logger>();
|
||||||
|
|
||||||
taskBroker = new TaskBroker(loggerMock, mock(), mock());
|
taskBroker = new TaskBroker(loggerMock, mock(), mock(), mock());
|
||||||
taskBroker.registerRunner(runner, messageCallback);
|
taskBroker.registerRunner(runner, messageCallback);
|
||||||
|
|
||||||
const offer: TaskOffer = {
|
const offer: TaskOffer = {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { Logger } from '@n8n/backend-common';
|
import { Logger } from '@n8n/backend-common';
|
||||||
import { TaskRunnersConfig } from '@n8n/config';
|
import { GlobalConfig, TaskRunnersConfig } from '@n8n/config';
|
||||||
import { Service } from '@n8n/di';
|
import { Service } from '@n8n/di';
|
||||||
import type {
|
import type {
|
||||||
BrokerMessage,
|
BrokerMessage,
|
||||||
@@ -10,7 +10,6 @@ import type {
|
|||||||
import { UnexpectedError, UserError } from 'n8n-workflow';
|
import { UnexpectedError, UserError } from 'n8n-workflow';
|
||||||
import { nanoid } from 'nanoid';
|
import { nanoid } from 'nanoid';
|
||||||
|
|
||||||
import config from '@/config';
|
|
||||||
import { Time } from '@/constants';
|
import { Time } from '@/constants';
|
||||||
import { TaskDeferredError } from '@/task-runners/task-broker/errors/task-deferred.error';
|
import { TaskDeferredError } from '@/task-runners/task-broker/errors/task-deferred.error';
|
||||||
import { TaskRejectError } from '@/task-runners/task-broker/errors/task-reject.error';
|
import { TaskRejectError } from '@/task-runners/task-broker/errors/task-reject.error';
|
||||||
@@ -91,6 +90,7 @@ export class TaskBroker {
|
|||||||
private readonly logger: Logger,
|
private readonly logger: Logger,
|
||||||
private readonly taskRunnersConfig: TaskRunnersConfig,
|
private readonly taskRunnersConfig: TaskRunnersConfig,
|
||||||
private readonly taskRunnerLifecycleEvents: TaskRunnerLifecycleEvents,
|
private readonly taskRunnerLifecycleEvents: TaskRunnerLifecycleEvents,
|
||||||
|
private readonly globalConfig: GlobalConfig,
|
||||||
) {
|
) {
|
||||||
if (this.taskRunnersConfig.taskTimeout <= 0) {
|
if (this.taskRunnersConfig.taskTimeout <= 0) {
|
||||||
throw new UserError('Task timeout must be greater than 0');
|
throw new UserError('Task timeout must be greater than 0');
|
||||||
@@ -471,7 +471,7 @@ export class TaskBroker {
|
|||||||
taskId,
|
taskId,
|
||||||
new TaskRunnerExecutionTimeoutError({
|
new TaskRunnerExecutionTimeoutError({
|
||||||
taskTimeout,
|
taskTimeout,
|
||||||
isSelfHosted: config.getEnv('deployment.type') !== 'cloud',
|
isSelfHosted: this.globalConfig.deployment.type !== 'cloud',
|
||||||
mode,
|
mode,
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user