UNPKG

n8n

Version:

n8n Workflow Automation Tool

150 lines 7.24 kB
"use strict"; var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; var __metadata = (this && this.__metadata) || function (k, v) { if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.PruningService = void 0; const typedi_1 = require("typedi"); const n8n_core_1 = require("n8n-core"); const constants_1 = require("../constants"); const config_1 = __importDefault(require("../config")); const execution_repository_1 = require("../databases/repositories/execution.repository"); const Logger_1 = require("../Logger"); const n8n_workflow_1 = require("n8n-workflow"); const OnShutdown_1 = require("../decorators/OnShutdown"); const orchestration_service_1 = require("./orchestration.service"); let PruningService = class PruningService { constructor(logger, instanceSettings, executionRepository, binaryDataService, orchestrationService) { this.logger = logger; this.instanceSettings = instanceSettings; this.executionRepository = executionRepository; this.binaryDataService = binaryDataService; this.orchestrationService = orchestrationService; this.hardDeletionBatchSize = 100; this.rates = { softDeletion: config_1.default.getEnv('executions.pruneDataIntervals.softDelete') * constants_1.TIME.MINUTE, hardDeletion: config_1.default.getEnv('executions.pruneDataIntervals.hardDelete') * constants_1.TIME.MINUTE, }; this.isShuttingDown = false; } init() { const { isLeader, isMultiMainSetupEnabled } = this.orchestrationService; if (isLeader) this.startPruning(); if (isMultiMainSetupEnabled) { this.orchestrationService.multiMainSetup.on('leader-takeover', () => this.startPruning()); this.orchestrationService.multiMainSetup.on('leader-stepdown', () => this.stopPruning()); } } isPruningEnabled() { if (!config_1.default.getEnv('executions.pruneData') || constants_1.inTest || config_1.default.get('generic.instanceType') !== 'main') { return false; } if (config_1.default.getEnv('multiMainSetup.enabled') && config_1.default.getEnv('generic.instanceType') === 'main' && this.instanceSettings.isFollower) { return false; } return true; } startPruning() { if (!this.isPruningEnabled()) return; if (this.isShuttingDown) { this.logger.warn('[Pruning] Cannot start pruning while shutting down'); return; } this.logger.debug('[Pruning] Starting soft-deletion and hard-deletion timers'); this.setSoftDeletionInterval(); this.scheduleHardDeletion(); } stopPruning() { if (!this.isPruningEnabled()) return; this.logger.debug('[Pruning] Removing soft-deletion and hard-deletion timers'); clearInterval(this.softDeletionInterval); clearTimeout(this.hardDeletionTimeout); } setSoftDeletionInterval(rateMs = this.rates.softDeletion) { const when = [rateMs / constants_1.TIME.MINUTE, 'min'].join(' '); this.softDeletionInterval = setInterval(async () => await this.softDeleteOnPruningCycle(), this.rates.softDeletion); this.logger.debug(`[Pruning] Soft-deletion scheduled every ${when}`); } scheduleHardDeletion(rateMs = this.rates.hardDeletion) { const when = [rateMs / constants_1.TIME.MINUTE, 'min'].join(' '); this.hardDeletionTimeout = setTimeout(() => { this.hardDeleteOnPruningCycle() .then((rate) => this.scheduleHardDeletion(rate)) .catch((error) => { this.scheduleHardDeletion(1 * constants_1.TIME.SECOND); const errorMessage = error instanceof Error ? error.message : (0, n8n_workflow_1.jsonStringify)(error, { replaceCircularRefs: true }); this.logger.error('[Pruning] Failed to hard-delete executions', { errorMessage }); }); }, rateMs); this.logger.debug(`[Pruning] Hard-deletion scheduled for next ${when}`); } async softDeleteOnPruningCycle() { this.logger.debug('[Pruning] Starting soft-deletion of executions'); const result = await this.executionRepository.softDeletePrunableExecutions(); if (result.affected === 0) { this.logger.debug('[Pruning] Found no executions to soft-delete'); return; } this.logger.debug('[Pruning] Soft-deleted executions', { count: result.affected }); } shutdown() { this.isShuttingDown = true; this.stopPruning(); } async hardDeleteOnPruningCycle() { const ids = await this.executionRepository.hardDeleteSoftDeletedExecutions(); const executionIds = ids.map((o) => o.executionId); if (executionIds.length === 0) { this.logger.debug('[Pruning] Found no executions to hard-delete'); return this.rates.hardDeletion; } try { this.logger.debug('[Pruning] Starting hard-deletion of executions', { executionIds }); await this.binaryDataService.deleteMany(ids); await this.executionRepository.deleteByIds(executionIds); this.logger.debug('[Pruning] Hard-deleted executions', { executionIds }); } catch (error) { this.logger.error('[Pruning] Failed to hard-delete executions', { executionIds, error: error instanceof Error ? error.message : `${error}`, }); } const isHighVolume = executionIds.length >= this.hardDeletionBatchSize; return isHighVolume ? 1 * constants_1.TIME.SECOND : this.rates.hardDeletion; } }; exports.PruningService = PruningService; __decorate([ (0, OnShutdown_1.OnShutdown)(), __metadata("design:type", Function), __metadata("design:paramtypes", []), __metadata("design:returntype", void 0) ], PruningService.prototype, "shutdown", null); exports.PruningService = PruningService = __decorate([ (0, typedi_1.Service)(), __metadata("design:paramtypes", [Logger_1.Logger, n8n_core_1.InstanceSettings, execution_repository_1.ExecutionRepository, n8n_core_1.BinaryDataService, orchestration_service_1.OrchestrationService]) ], PruningService); //# sourceMappingURL=pruning.service.js.map