mirror of
https://github.com/Abdulazizzn/n8n-enterprise-unlocked.git
synced 2025-12-17 01:56:46 +00:00
refactor(core): Port workflow history config (#14689)
This commit is contained in:
12
packages/@n8n/config/src/configs/workflow-history.config.ts
Normal file
12
packages/@n8n/config/src/configs/workflow-history.config.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
import { Config, Env } from '../decorators';
|
||||
|
||||
@Config
|
||||
export class WorkflowHistoryConfig {
|
||||
/** Whether to save workflow history versions. */
|
||||
@Env('N8N_WORKFLOW_HISTORY_ENABLED')
|
||||
enabled: boolean = true;
|
||||
|
||||
/** Time (in hours) to keep workflow history versions for. `-1` means forever. */
|
||||
@Env('N8N_WORKFLOW_HISTORY_PRUNE_TIME')
|
||||
pruneTime: number = -1;
|
||||
}
|
||||
@@ -27,6 +27,7 @@ import { TagsConfig } from './configs/tags.config';
|
||||
import { TemplatesConfig } from './configs/templates.config';
|
||||
import { UserManagementConfig } from './configs/user-management.config';
|
||||
import { VersionNotificationsConfig } from './configs/version-notifications.config';
|
||||
import { WorkflowHistoryConfig } from './configs/workflow-history.config';
|
||||
import { WorkflowsConfig } from './configs/workflows.config';
|
||||
import { Config, Env, Nested } from './decorators';
|
||||
|
||||
@@ -149,4 +150,7 @@ export class GlobalConfig {
|
||||
|
||||
@Nested
|
||||
partialExecutions: PartialExecutionsConfig;
|
||||
|
||||
@Nested
|
||||
workflowHistory: WorkflowHistoryConfig;
|
||||
}
|
||||
|
||||
@@ -315,6 +315,10 @@ describe('GlobalConfig', () => {
|
||||
partialExecutions: {
|
||||
version: 2,
|
||||
},
|
||||
workflowHistory: {
|
||||
enabled: true,
|
||||
pruneTime: -1,
|
||||
},
|
||||
};
|
||||
|
||||
it('should use all default values when no env variables are defined', () => {
|
||||
|
||||
@@ -301,22 +301,6 @@ export const schema = {
|
||||
},
|
||||
},
|
||||
|
||||
workflowHistory: {
|
||||
enabled: {
|
||||
doc: 'Whether to save workflow history versions',
|
||||
format: Boolean,
|
||||
default: true,
|
||||
env: 'N8N_WORKFLOW_HISTORY_ENABLED',
|
||||
},
|
||||
|
||||
pruneTime: {
|
||||
doc: 'Time (in hours) to keep workflow history versions for',
|
||||
format: Number,
|
||||
default: -1,
|
||||
env: 'N8N_WORKFLOW_HISTORY_PRUNE_TIME',
|
||||
},
|
||||
},
|
||||
|
||||
proxy_hops: {
|
||||
format: Number,
|
||||
default: 0,
|
||||
|
||||
@@ -320,7 +320,7 @@ export class FrontendService {
|
||||
debugInEditor: this.license.isDebugInEditorLicensed(),
|
||||
binaryDataS3: isS3Available && isS3Selected && isS3Licensed,
|
||||
workflowHistory:
|
||||
this.license.isWorkflowHistoryLicensed() && config.getEnv('workflowHistory.enabled'),
|
||||
this.license.isWorkflowHistoryLicensed() && this.globalConfig.workflowHistory.enabled,
|
||||
workerView: this.license.isWorkerViewLicensed(),
|
||||
advancedPermissions: this.license.isAdvancedPermissionsLicensed(),
|
||||
apiKeyScopes: this.license.isApiKeyScopesEnabled(),
|
||||
@@ -344,7 +344,7 @@ export class FrontendService {
|
||||
this.settings.variables.limit = this.license.getVariablesLimit();
|
||||
}
|
||||
|
||||
if (this.license.isWorkflowHistoryLicensed() && config.getEnv('workflowHistory.enabled')) {
|
||||
if (this.globalConfig.workflowHistory.enabled && this.license.isWorkflowHistoryLicensed()) {
|
||||
Object.assign(this.settings.workflowHistory, {
|
||||
pruneTime: getWorkflowHistoryPruneTime(),
|
||||
licensePruneTime: getWorkflowHistoryLicensePruneTime(),
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
import config from '@/config';
|
||||
import { GlobalConfig } from '@n8n/config';
|
||||
import { Container } from '@n8n/di';
|
||||
|
||||
import { License } from '@/license';
|
||||
import { getWorkflowHistoryPruneTime } from '@/workflows/workflow-history.ee/workflow-history-helper.ee';
|
||||
import { mockInstance } from '@test/mocking';
|
||||
|
||||
let licensePruneTime = -1;
|
||||
const globalConfig = Container.get(GlobalConfig);
|
||||
|
||||
beforeAll(async () => {
|
||||
mockInstance(License, {
|
||||
@@ -15,39 +18,39 @@ beforeAll(async () => {
|
||||
|
||||
beforeEach(() => {
|
||||
licensePruneTime = -1;
|
||||
config.set('workflowHistory.pruneTime', -1);
|
||||
globalConfig.workflowHistory.pruneTime = -1;
|
||||
});
|
||||
|
||||
describe('getWorkflowHistoryPruneTime', () => {
|
||||
test('should return -1 (infinite) if config and license are -1', () => {
|
||||
licensePruneTime = -1;
|
||||
config.set('workflowHistory.pruneTime', -1);
|
||||
globalConfig.workflowHistory.pruneTime = -1;
|
||||
|
||||
expect(getWorkflowHistoryPruneTime()).toBe(-1);
|
||||
});
|
||||
|
||||
test('should return config time if license is infinite and config is not', () => {
|
||||
licensePruneTime = -1;
|
||||
config.set('workflowHistory.pruneTime', 24);
|
||||
globalConfig.workflowHistory.pruneTime = 24;
|
||||
|
||||
expect(getWorkflowHistoryPruneTime()).toBe(24);
|
||||
});
|
||||
|
||||
test('should return license time if config is infinite and license is not', () => {
|
||||
licensePruneTime = 25;
|
||||
config.set('workflowHistory.pruneTime', -1);
|
||||
globalConfig.workflowHistory.pruneTime = -1;
|
||||
|
||||
expect(getWorkflowHistoryPruneTime()).toBe(25);
|
||||
});
|
||||
|
||||
test('should return lowest of config and license time if both are not -1', () => {
|
||||
licensePruneTime = 26;
|
||||
config.set('workflowHistory.pruneTime', 100);
|
||||
globalConfig.workflowHistory.pruneTime = 100;
|
||||
|
||||
expect(getWorkflowHistoryPruneTime()).toBe(26);
|
||||
|
||||
licensePruneTime = 100;
|
||||
config.set('workflowHistory.pruneTime', 27);
|
||||
globalConfig.workflowHistory.pruneTime = 27;
|
||||
|
||||
expect(getWorkflowHistoryPruneTime()).toBe(27);
|
||||
});
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { GlobalConfig } from '@n8n/config';
|
||||
import { Container } from '@n8n/di';
|
||||
|
||||
import config from '@/config';
|
||||
import { License } from '@/license';
|
||||
|
||||
export function isWorkflowHistoryLicensed() {
|
||||
@@ -9,7 +9,7 @@ export function isWorkflowHistoryLicensed() {
|
||||
}
|
||||
|
||||
export function isWorkflowHistoryEnabled() {
|
||||
return isWorkflowHistoryLicensed() && config.getEnv('workflowHistory.enabled');
|
||||
return isWorkflowHistoryLicensed() && Container.get(GlobalConfig).workflowHistory.enabled;
|
||||
}
|
||||
|
||||
export function getWorkflowHistoryLicensePruneTime() {
|
||||
@@ -19,7 +19,7 @@ export function getWorkflowHistoryLicensePruneTime() {
|
||||
// Time in hours
|
||||
export function getWorkflowHistoryPruneTime(): number {
|
||||
const licenseTime = Container.get(License).getWorkflowHistoryPruneLimit();
|
||||
const configTime = config.getEnv('workflowHistory.pruneTime');
|
||||
const configTime = Container.get(GlobalConfig).workflowHistory.pruneTime;
|
||||
|
||||
// License is infinite and config time is infinite
|
||||
if (licenseTime === -1) {
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { GlobalConfig } from '@n8n/config';
|
||||
import { Container } from '@n8n/di';
|
||||
import { In } from '@n8n/typeorm';
|
||||
import { DateTime } from 'luxon';
|
||||
|
||||
import config from '@/config';
|
||||
import { WorkflowHistoryRepository } from '@/databases/repositories/workflow-history.repository';
|
||||
import { License } from '@/license';
|
||||
import { WorkflowHistoryManager } from '@/workflows/workflow-history.ee/workflow-history-manager.ee';
|
||||
@@ -16,19 +16,21 @@ describe('Workflow History Manager', () => {
|
||||
const license = mockInstance(License);
|
||||
let repo: WorkflowHistoryRepository;
|
||||
let manager: WorkflowHistoryManager;
|
||||
let globalConfig: GlobalConfig;
|
||||
|
||||
beforeAll(async () => {
|
||||
await testDb.init();
|
||||
repo = Container.get(WorkflowHistoryRepository);
|
||||
manager = Container.get(WorkflowHistoryManager);
|
||||
globalConfig = Container.get(GlobalConfig);
|
||||
});
|
||||
|
||||
beforeEach(async () => {
|
||||
await testDb.truncate(['Workflow']);
|
||||
jest.clearAllMocks();
|
||||
|
||||
config.set('workflowHistory.enabled', true);
|
||||
config.set('workflowHistory.pruneTime', -1);
|
||||
globalConfig.workflowHistory.enabled = true;
|
||||
globalConfig.workflowHistory.pruneTime = -1;
|
||||
|
||||
license.isWorkflowHistoryLicensed.mockReturnValue(true);
|
||||
license.getWorkflowHistoryPruneLimit.mockReturnValue(-1);
|
||||
@@ -64,7 +66,7 @@ describe('Workflow History Manager', () => {
|
||||
});
|
||||
|
||||
test('should not prune when licensed but disabled', async () => {
|
||||
config.set('workflowHistory.enabled', false);
|
||||
globalConfig.workflowHistory.enabled = false;
|
||||
await createWorkflowHistory();
|
||||
await pruneAndAssertCount();
|
||||
});
|
||||
@@ -75,7 +77,7 @@ describe('Workflow History Manager', () => {
|
||||
});
|
||||
|
||||
test('should prune when config prune time is not -1 (infinite)', async () => {
|
||||
config.set('workflowHistory.pruneTime', 24);
|
||||
globalConfig.workflowHistory.pruneTime = 24;
|
||||
await createWorkflowHistory();
|
||||
await pruneAndAssertCount(0);
|
||||
});
|
||||
@@ -88,7 +90,7 @@ describe('Workflow History Manager', () => {
|
||||
});
|
||||
|
||||
test('should only prune versions older than prune time', async () => {
|
||||
config.set('workflowHistory.pruneTime', 24);
|
||||
globalConfig.workflowHistory.pruneTime = 24;
|
||||
|
||||
const recentVersions = await createWorkflowHistory(0);
|
||||
const oldVersions = await createWorkflowHistory();
|
||||
|
||||
Reference in New Issue
Block a user