UNPKG

n8n

Version:

n8n Workflow Automation Tool

314 lines 14.1 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.MessageEventBusLogWriter = void 0; const config_1 = require("@n8n/config"); const di_1 = require("@n8n/di"); const events_1 = require("events"); const fs_1 = require("fs"); const remove_1 = __importDefault(require("lodash/remove")); const n8n_core_1 = require("n8n-core"); const n8n_workflow_1 = require("n8n-workflow"); const path_1 = __importStar(require("path")); const readline_1 = __importDefault(require("readline")); const worker_threads_1 = require("worker_threads"); const constants_1 = require("../../constants"); const abstract_event_message_1 = require("../event-message-classes/abstract-event-message"); const event_message_audit_1 = require("../event-message-classes/event-message-audit"); const event_message_confirm_1 = require("../event-message-classes/event-message-confirm"); const event_message_generic_1 = require("../event-message-classes/event-message-generic"); const event_message_node_1 = require("../event-message-classes/event-message-node"); const event_message_workflow_1 = require("../event-message-classes/event-message-workflow"); class MessageEventBusLogWriter { constructor() { this.logger = di_1.Container.get(n8n_core_1.Logger); this.globalConfig = di_1.Container.get(config_1.GlobalConfig); } get worker() { return this._worker; } static async getInstance(options) { if (!MessageEventBusLogWriter.instance) { MessageEventBusLogWriter.instance = new MessageEventBusLogWriter(); MessageEventBusLogWriter.options = { logFullBasePath: path_1.default.join(options?.logBasePath ?? di_1.Container.get(n8n_core_1.InstanceSettings).n8nFolder, options?.logBaseName ?? di_1.Container.get(config_1.GlobalConfig).eventBus.logWriter.logBaseName), keepNumberOfFiles: options?.keepNumberOfFiles ?? di_1.Container.get(config_1.GlobalConfig).eventBus.logWriter.keepLogCount, maxFileSizeInKB: options?.maxFileSizeInKB ?? di_1.Container.get(config_1.GlobalConfig).eventBus.logWriter.maxFileSizeInKB, }; await MessageEventBusLogWriter.instance.startThread(); } return MessageEventBusLogWriter.instance; } startLogging() { if (this.worker) { this.worker.postMessage({ command: 'startLogging', data: {} }); } } startRecoveryProcess() { if (this.worker) { this.worker.postMessage({ command: 'startRecoveryProcess', data: {} }); } } isRecoveryProcessRunning() { return (0, fs_1.existsSync)(this.getRecoveryInProgressFileName()); } endRecoveryProcess() { if (this.worker) { this.worker.postMessage({ command: 'endRecoveryProcess', data: {} }); } } async startThread() { if (this.worker) { await this.close(); } await MessageEventBusLogWriter.instance.spawnThread(); if (this.worker) { this.worker.postMessage({ command: 'initialize', data: MessageEventBusLogWriter.options }); } } async spawnThread() { const parsedName = (0, path_1.parse)(__filename); let workerFileName; if (constants_1.inTest) { workerFileName = './dist/eventbus/message-event-bus-writer/message-event-bus-log-writer-worker.js'; } else { workerFileName = path_1.default.join(parsedName.dir, `${parsedName.name}-worker${parsedName.ext}`); } this._worker = new worker_threads_1.Worker(workerFileName); if (this.worker) { this.worker.on('messageerror', async (error) => { this.logger.error('Event Bus Log Writer thread error, attempting to restart...', { error }); await MessageEventBusLogWriter.instance.startThread(); }); return true; } return false; } async close() { if (this.worker) { await this.worker.terminate(); this._worker = undefined; } } putMessage(msg) { if (this.worker) { this.worker.postMessage({ command: 'appendMessageToLog', data: msg.serialize() }); } } confirmMessageSent(msgId, source) { if (this.worker) { this.worker.postMessage({ command: 'confirmMessageSent', data: new event_message_confirm_1.EventMessageConfirm(msgId, source).serialize(), }); } } async getMessages(mode = 'all', logHistory = 1) { const results = { loggedMessages: [], sentMessages: [], unfinishedExecutions: {}, }; const configLogCount = this.globalConfig.eventBus.logWriter.keepLogCount; const logCount = logHistory ? Math.min(configLogCount, logHistory) : configLogCount; for (let i = logCount; i >= 0; i--) { const logFileName = this.getLogFileName(i); if (logFileName) { await this.readLoggedMessagesFromFile(results, mode, logFileName); } } return results; } async readLoggedMessagesFromFile(results, mode, logFileName) { if (logFileName && (0, fs_1.existsSync)(logFileName)) { try { const rl = readline_1.default.createInterface({ input: (0, fs_1.createReadStream)(logFileName), crlfDelay: Infinity, }); rl.on('line', (line) => { try { const json = (0, n8n_workflow_1.jsonParse)(line); if ((0, abstract_event_message_1.isEventMessageOptions)(json) && json.__type !== undefined) { const msg = this.getEventMessageObjectByType(json); if (msg !== null) results.loggedMessages.push(msg); if (msg?.eventName && msg.payload?.executionId) { const executionId = msg.payload.executionId; switch (msg.eventName) { case 'n8n.workflow.started': if (!Object.keys(results.unfinishedExecutions).includes(executionId)) { results.unfinishedExecutions[executionId] = []; } results.unfinishedExecutions[executionId] = [msg]; break; case 'n8n.workflow.success': case 'n8n.workflow.failed': case 'n8n.execution.throttled': case 'n8n.execution.started-during-bootup': delete results.unfinishedExecutions[executionId]; break; case 'n8n.node.started': case 'n8n.node.finished': if (!Object.keys(results.unfinishedExecutions).includes(executionId)) { results.unfinishedExecutions[executionId] = []; } results.unfinishedExecutions[executionId].push(msg); break; } } } if ((0, event_message_confirm_1.isEventMessageConfirm)(json) && mode !== 'all') { const removedMessage = (0, remove_1.default)(results.loggedMessages, (e) => e.id === json.confirm); if (mode === 'sent') { results.sentMessages.push(...removedMessage); } } } catch (error) { this.logger.error(`Error reading line messages from file: ${logFileName}, line: ${line}, ${error.message}}`); } }); await (0, events_1.once)(rl, 'close'); } catch { this.logger.error(`Error reading logged messages from file: ${logFileName}`); } } return results; } getLogFileName(counter) { if (counter) { return `${MessageEventBusLogWriter.options.logFullBasePath}-${counter}.log`; } else { return `${MessageEventBusLogWriter.options.logFullBasePath}.log`; } } getRecoveryInProgressFileName() { return `${MessageEventBusLogWriter.options.logFullBasePath}.recoveryInProgress`; } cleanAllLogs() { for (let i = 0; i <= MessageEventBusLogWriter.options.keepNumberOfFiles; i++) { if ((0, fs_1.existsSync)(this.getLogFileName(i))) { (0, fs_1.rmSync)(this.getLogFileName(i)); } } } async getMessagesByExecutionId(executionId, logHistory) { const result = []; const configLogCount = this.globalConfig.eventBus.logWriter.keepLogCount; const logCount = logHistory ? Math.min(configLogCount, logHistory) : configLogCount; for (let i = 0; i < logCount; i++) { const logFileName = this.getLogFileName(i); if (logFileName) { result.push(...(await this.readFromFileByExecutionId(executionId, logFileName))); } } return result.sort((a, b) => a.ts.diff(b.ts).toMillis()); } async readFromFileByExecutionId(executionId, logFileName) { const messages = []; if (logFileName && (0, fs_1.existsSync)(logFileName)) { try { const rl = readline_1.default.createInterface({ input: (0, fs_1.createReadStream)(logFileName), crlfDelay: Infinity, }); rl.on('line', (line) => { try { const json = (0, n8n_workflow_1.jsonParse)(line); if ((0, abstract_event_message_1.isEventMessageOptions)(json) && json.__type !== undefined && json.payload?.executionId === executionId) { const msg = this.getEventMessageObjectByType(json); if (msg !== null) messages.push(msg); } } catch { this.logger.error(`Error reading line messages from file: ${logFileName}, line: ${line}`); } }); await (0, events_1.once)(rl, 'close'); } catch { this.logger.error(`Error reading logged messages from file: ${logFileName}`); } } return messages; } async getMessagesAll() { return (await this.getMessages('all')).loggedMessages; } async getMessagesSent() { return (await this.getMessages('sent')).sentMessages; } async getMessagesUnsent() { return (await this.getMessages('unsent')).loggedMessages; } async getUnfinishedExecutions() { return (await this.getMessages('unfinished')).unfinishedExecutions; } async getUnsentAndUnfinishedExecutions() { const result = await this.getMessages('unsent'); return { unsentMessages: result.loggedMessages, unfinishedExecutions: result.unfinishedExecutions, }; } getEventMessageObjectByType(message) { switch (message.__type) { case "$$EventMessage": return new event_message_generic_1.EventMessageGeneric(message); case "$$EventMessageWorkflow": return new event_message_workflow_1.EventMessageWorkflow(message); case "$$EventMessageAudit": return new event_message_audit_1.EventMessageAudit(message); case "$$EventMessageNode": return new event_message_node_1.EventMessageNode(message); default: return null; } } } exports.MessageEventBusLogWriter = MessageEventBusLogWriter; //# sourceMappingURL=message-event-bus-log-writer.js.map