n8n
Version:
n8n Workflow Automation Tool
318 lines • 15.8 kB
JavaScript
"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 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 EventMessageNode_1 = require("../EventMessageClasses/EventMessageNode");
const EventMessageGeneric_1 = require("../EventMessageClasses/EventMessageGeneric");
const execution_recovery_service_1 = require("../../executions/execution-recovery.service");
const EventMessageAiNode_1 = require("../EventMessageClasses/EventMessageAiNode");
const License_1 = require("../../License");
const EventMessageExecution_1 = require("../EventMessageClasses/EventMessageExecution");
const config_2 = require("@n8n/config");
let MessageEventBus = class MessageEventBus extends events_1.default {
constructor(logger, executionRepository, eventDestinationsRepository, workflowRepository, orchestrationService, recoveryService, license, globalConfig) {
super();
this.logger = logger;
this.executionRepository = executionRepository;
this.eventDestinationsRepository = eventDestinationsRepository;
this.workflowRepository = workflowRepository;
this.orchestrationService = orchestrationService;
this.recoveryService = recoveryService;
this.license = license;
this.globalConfig = globalConfig;
this.isInitialized = false;
this.destinations = {};
}
async initialize(options) {
var _a, _b, _c, _d, _e, _f;
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 = this.globalConfig.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', '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 || this.globalConfig.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) {
const logMesssages = unsentAndUnfinished.unfinishedExecutions[executionId];
await this.recoveryService.recoverFromLogs(executionId, logMesssages !== null && logMesssages !== void 0 ? logMesssages : []);
}
}
(_f = this.logWriter) === null || _f === void 0 ? void 0 : _f.endRecoveryProcess();
}
}
if (this.globalConfig.eventBus.checkUnsentInterval > 0) {
if (this.pushIntervalTimer) {
clearInterval(this.pushIntervalTimer);
}
this.pushIntervalTimer = setInterval(async () => {
await this.trySendingUnsent();
}, this.globalConfig.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 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('metrics.eventBus.event', 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 (this.license.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));
}
async sendExecutionEvent(options) {
await this.send(new EventMessageExecution_1.EventMessageExecution(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,
execution_recovery_service_1.ExecutionRecoveryService,
License_1.License,
config_2.GlobalConfig])
], MessageEventBus);
//# sourceMappingURL=MessageEventBus.js.map