UNPKG

n8n

Version:

n8n Workflow Automation Tool

328 lines 16.5 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.MessageEventBus = void 0; const typedi_1 = require("typedi"); const typeorm_1 = require("@n8n/typeorm"); const events_1 = __importDefault(require("events")); const uniqBy_1 = __importDefault(require("lodash/uniqBy")); const n8n_workflow_1 = require("n8n-workflow"); const config_1 = __importDefault(require("../../config")); const eventDestinations_repository_1 = require("../../databases/repositories/eventDestinations.repository"); const execution_repository_1 = require("../../databases/repositories/execution.repository"); const workflow_repository_1 = require("../../databases/repositories/workflow.repository"); const orchestration_service_1 = require("../../services/orchestration.service"); const Logger_1 = require("../../Logger"); const MessageEventBusLogWriter_1 = require("../MessageEventBusWriter/MessageEventBusLogWriter"); const MessageEventBusDestinationFromDb_1 = require("../MessageEventBusDestination/MessageEventBusDestinationFromDb"); const EventMessageAudit_1 = require("../EventMessageClasses/EventMessageAudit"); const EventMessageWorkflow_1 = require("../EventMessageClasses/EventMessageWorkflow"); const MessageEventBusHelper_1 = require("./MessageEventBusHelper"); const EventMessageNode_1 = require("../EventMessageClasses/EventMessageNode"); const EventMessageGeneric_1 = require("../EventMessageClasses/EventMessageGeneric"); const Helpers_ee_1 = require("../MessageEventBusDestination/Helpers.ee"); const Helpers_1 = require("../EventMessageClasses/Helpers"); const executionDataRecovery_service_1 = require("../executionDataRecovery.service"); const EventMessageAiNode_1 = require("../EventMessageClasses/EventMessageAiNode"); let MessageEventBus = class MessageEventBus extends events_1.default { constructor(logger, executionRepository, eventDestinationsRepository, workflowRepository, orchestrationService, recoveryService) { super(); this.logger = logger; this.executionRepository = executionRepository; this.eventDestinationsRepository = eventDestinationsRepository; this.workflowRepository = workflowRepository; this.orchestrationService = orchestrationService; this.recoveryService = recoveryService; this.isInitialized = false; this.destinations = {}; } async initialize(options) { var _a, _b, _c, _d, _e, _f, _g; if (this.isInitialized) { return; } this.logger.debug('Initializing event bus...'); const savedEventDestinations = await this.eventDestinationsRepository.find({}); if (savedEventDestinations.length > 0) { for (const destinationData of savedEventDestinations) { try { const destination = (0, MessageEventBusDestinationFromDb_1.messageEventBusDestinationFromDb)(this, destinationData); if (destination) { await this.addDestination(destination, false); } } catch (error) { if (error.message) this.logger.debug(error.message); } } } this.logger.debug('Initializing event writer'); if (options === null || options === void 0 ? void 0 : options.workerId) { const logBaseName = config_1.default.getEnv('eventBus.logWriter.logBaseName') + '-worker'; this.logWriter = await MessageEventBusLogWriter_1.MessageEventBusLogWriter.getInstance({ logBaseName, }); } else { this.logWriter = await MessageEventBusLogWriter_1.MessageEventBusLogWriter.getInstance(); } if (!this.logWriter) { this.logger.warn('Could not initialize event writer'); } if (options === null || options === void 0 ? void 0 : options.skipRecoveryPass) { this.logger.debug('Skipping unsent event check'); } else { this.logger.debug('Checking for unsent event messages'); const unsentAndUnfinished = await this.getUnsentAndUnfinishedExecutions(); this.logger.debug(`Start logging into ${(_b = (_a = this.logWriter) === null || _a === void 0 ? void 0 : _a.getLogFileName()) !== null && _b !== void 0 ? _b : 'unknown filename'} `); (_c = this.logWriter) === null || _c === void 0 ? void 0 : _c.startLogging(); await this.send(unsentAndUnfinished.unsentMessages); let unfinishedExecutionIds = Object.keys(unsentAndUnfinished.unfinishedExecutions); if (config_1.default.get('executions.mode') !== 'queue') { const dbUnfinishedExecutionIds = (await this.executionRepository.find({ where: { status: (0, typeorm_1.In)(['running', 'new', 'unknown']), }, select: ['id'], })).map((e) => e.id); unfinishedExecutionIds = Array.from(new Set([...unfinishedExecutionIds, ...dbUnfinishedExecutionIds])); } if (unfinishedExecutionIds.length > 0) { this.logger.warn(`Found unfinished executions: ${unfinishedExecutionIds.join(', ')}`); this.logger.info('This could be due to a crash of an active workflow or a restart of n8n.'); const activeWorkflows = await this.workflowRepository.find({ where: { active: true }, select: ['id', 'name'], }); if (activeWorkflows.length > 0) { this.logger.info('Currently active workflows:'); for (const workflowData of activeWorkflows) { this.logger.info(` - ${workflowData.name} (ID: ${workflowData.id})`); } } const recoveryAlreadyAttempted = (_d = this.logWriter) === null || _d === void 0 ? void 0 : _d.isRecoveryProcessRunning(); if (recoveryAlreadyAttempted || config_1.default.getEnv('eventBus.crashRecoveryMode') === 'simple') { await this.executionRepository.markAsCrashed(unfinishedExecutionIds); if (recoveryAlreadyAttempted) this.logger.warn('Skipped recovery process since it previously failed.'); } else { (_e = this.logWriter) === null || _e === void 0 ? void 0 : _e.startRecoveryProcess(); for (const executionId of unfinishedExecutionIds) { this.logger.warn(`Attempting to recover execution ${executionId}`); if (!((_f = unsentAndUnfinished.unfinishedExecutions[executionId]) === null || _f === void 0 ? void 0 : _f.length)) { this.logger.debug(`No event messages found, marking execution ${executionId} as 'crashed'`); await this.executionRepository.markAsCrashed([executionId]); } else { await this.recoveryService.recoverExecutionData(executionId, unsentAndUnfinished.unfinishedExecutions[executionId], true); } } } (_g = this.logWriter) === null || _g === void 0 ? void 0 : _g.endRecoveryProcess(); } } if (config_1.default.getEnv('eventBus.checkUnsentInterval') > 0) { if (this.pushIntervalTimer) { clearInterval(this.pushIntervalTimer); } this.pushIntervalTimer = setInterval(async () => { await this.trySendingUnsent(); }, config_1.default.getEnv('eventBus.checkUnsentInterval')); } this.logger.debug('MessageEventBus initialized'); this.isInitialized = true; } async addDestination(destination, notifyWorkers = true) { await this.removeDestination(destination.getId(), false); this.destinations[destination.getId()] = destination; this.destinations[destination.getId()].startListening(); if (notifyWorkers) { await this.orchestrationService.publish('restartEventBus'); } return destination; } async findDestination(id) { let result; if (id && Object.keys(this.destinations).includes(id)) { result = [this.destinations[id].serialize()]; } else { result = Object.keys(this.destinations).map((e) => this.destinations[e].serialize()); } return result.sort((a, b) => { var _a, _b; return ((_a = a.__type) !== null && _a !== void 0 ? _a : '').localeCompare((_b = b.__type) !== null && _b !== void 0 ? _b : ''); }); } async removeDestination(id, notifyWorkers = true) { let result; if (Object.keys(this.destinations).includes(id)) { await this.destinations[id].close(); result = await this.destinations[id].deleteFromDb(); delete this.destinations[id]; } if (notifyWorkers) { await this.orchestrationService.publish('restartEventBus'); } return result; } async handleRedisEventBusMessage(messageString) { const eventData = (0, n8n_workflow_1.jsonParse)(messageString); if (eventData) { const eventMessage = (0, Helpers_1.getEventMessageObjectByType)(eventData); if (eventMessage) { await this.send(eventMessage); } } return eventData; } async trySendingUnsent(msgs) { const unsentMessages = msgs !== null && msgs !== void 0 ? msgs : (await this.getEventsUnsent()); if (unsentMessages.length > 0) { this.logger.debug(`Found unsent event messages: ${unsentMessages.length}`); for (const unsentMsg of unsentMessages) { this.logger.debug(`Retrying: ${unsentMsg.id} ${unsentMsg.__type}`); await this.emitMessage(unsentMsg); } } } async close() { var _a; this.logger.debug('Shutting down event writer...'); await ((_a = this.logWriter) === null || _a === void 0 ? void 0 : _a.close()); for (const destinationName of Object.keys(this.destinations)) { this.logger.debug(`Shutting down event destination ${this.destinations[destinationName].getId()}...`); await this.destinations[destinationName].close(); } this.isInitialized = false; this.logger.debug('EventBus shut down.'); } async restart() { await this.close(); await this.initialize({ skipRecoveryPass: true }); } async send(msgs) { var _a; if (!Array.isArray(msgs)) { msgs = [msgs]; } for (const msg of msgs) { (_a = this.logWriter) === null || _a === void 0 ? void 0 : _a.putMessage(msg); if (!this.shouldSendMsg(msg)) { this.confirmSent(msg, { id: '0', name: 'eventBus' }); } await this.emitMessage(msg); } } async testDestination(destinationId) { const msg = new EventMessageGeneric_1.EventMessageGeneric({ eventName: EventMessageGeneric_1.eventMessageGenericDestinationTestEvent, }); const destination = await this.findDestination(destinationId); if (destination.length > 0) { const sendResult = await this.destinations[destinationId].receiveFromEventBus({ msg, confirmCallback: () => this.confirmSent(msg, { id: '0', name: 'eventBus' }), }); return sendResult; } return false; } confirmSent(msg, source) { var _a; (_a = this.logWriter) === null || _a === void 0 ? void 0 : _a.confirmMessageSent(msg.id, source); } hasAnyDestinationSubscribedToEvent(msg) { for (const destinationName of Object.keys(this.destinations)) { if (this.destinations[destinationName].hasSubscribedToEvent(msg)) { return true; } } return false; } async emitMessage(msg) { this.emit(Helpers_ee_1.METRICS_EVENT_NAME, msg); this.emitMessageWithCallback('message', msg); if (this.shouldSendMsg(msg)) { for (const destinationName of Object.keys(this.destinations)) { this.emitMessageWithCallback(this.destinations[destinationName].getId(), msg); } } } emitMessageWithCallback(eventName, msg) { const confirmCallback = (message, src) => this.confirmSent(message, src); return this.emit(eventName, msg, confirmCallback); } shouldSendMsg(msg) { return ((0, MessageEventBusHelper_1.isLogStreamingEnabled)() && Object.keys(this.destinations).length > 0 && this.hasAnyDestinationSubscribedToEvent(msg)); } async getEventsAll() { var _a; const queryResult = await ((_a = this.logWriter) === null || _a === void 0 ? void 0 : _a.getMessagesAll()); const filtered = (0, uniqBy_1.default)(queryResult, 'id'); return filtered; } async getEventsSent() { var _a; const queryResult = await ((_a = this.logWriter) === null || _a === void 0 ? void 0 : _a.getMessagesSent()); const filtered = (0, uniqBy_1.default)(queryResult, 'id'); return filtered; } async getEventsUnsent() { var _a; const queryResult = await ((_a = this.logWriter) === null || _a === void 0 ? void 0 : _a.getMessagesUnsent()); const filtered = (0, uniqBy_1.default)(queryResult, 'id'); return filtered; } async getUnfinishedExecutions() { var _a; const queryResult = await ((_a = this.logWriter) === null || _a === void 0 ? void 0 : _a.getUnfinishedExecutions()); return queryResult; } async getUnsentAndUnfinishedExecutions() { var _a; const queryResult = await ((_a = this.logWriter) === null || _a === void 0 ? void 0 : _a.getUnsentAndUnfinishedExecutions()); return queryResult; } async getEventsByExecutionId(executionId, logHistory) { var _a; const result = await ((_a = this.logWriter) === null || _a === void 0 ? void 0 : _a.getMessagesByExecutionId(executionId, logHistory)); return result; } async sendAuditEvent(options) { await this.send(new EventMessageAudit_1.EventMessageAudit(options)); } async sendWorkflowEvent(options) { await this.send(new EventMessageWorkflow_1.EventMessageWorkflow(options)); } async sendNodeEvent(options) { await this.send(new EventMessageNode_1.EventMessageNode(options)); } async sendAiNodeEvent(options) { await this.send(new EventMessageAiNode_1.EventMessageAiNode(options)); } }; exports.MessageEventBus = MessageEventBus; exports.MessageEventBus = MessageEventBus = __decorate([ (0, typedi_1.Service)(), __metadata("design:paramtypes", [Logger_1.Logger, execution_repository_1.ExecutionRepository, eventDestinations_repository_1.EventDestinationsRepository, workflow_repository_1.WorkflowRepository, orchestration_service_1.OrchestrationService, executionDataRecovery_service_1.ExecutionDataRecoveryService]) ], MessageEventBus); //# sourceMappingURL=MessageEventBus.js.map