n8n
Version:
n8n Workflow Automation Tool
165 lines • 8.13 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);
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.PublicationStatusReporter = void 0;
const backend_common_1 = require("@n8n/backend-common");
const db_1 = require("@n8n/db");
const decorators_1 = require("@n8n/decorators");
const di_1 = require("@n8n/di");
const n8n_core_1 = require("n8n-core");
const activation_errors_service_1 = require("../../activation-errors.service");
const push_1 = require("../../push");
const publisher_service_1 = require("../../scaling/pubsub/publisher.service");
let PublicationStatusReporter = class PublicationStatusReporter {
constructor(logger, errorReporter, outboxRepository, activationErrorsService, push, publisher, triggerStatusRepository) {
this.logger = logger;
this.errorReporter = errorReporter;
this.outboxRepository = outboxRepository;
this.activationErrorsService = activationErrorsService;
this.push = push;
this.publisher = publisher;
this.triggerStatusRepository = triggerStatusRepository;
this.logger = this.logger.scoped('workflow-publication');
}
async report(record, result) {
switch (result.type) {
case 'completed': {
await this.complete(record, this.toRows(record, result.triggerStatuses));
this.pushStatus({
type: 'workflowActivated',
data: { workflowId: record.workflowId, activeVersionId: record.publishedVersionId },
});
return;
}
case 'unpublished': {
await this.complete(record, []);
this.pushStatus({
type: 'workflowDeactivated',
data: { workflowId: record.workflowId },
});
return;
}
case 'skipped': {
this.logSkip(record);
await this.complete(record);
return;
}
case 'version-missing': {
const errorMessage = 'Published version not found';
this.logger.warn('Published version not found, marking outbox record as failed', {
workflowId: record.workflowId,
publishedVersionId: record.publishedVersionId,
outboxId: record.id,
});
await this.outboxRepository.markFailed(record.id, errorMessage);
this.pushFailedToActivate(record.workflowId, errorMessage);
return;
}
case 'failed': {
const { triggerStatuses } = result;
await this.outboxRepository.manager.transaction(async (trx) => {
if (triggerStatuses) {
await this.triggerStatusRepository.replaceForWorkflow(record.workflowId, this.toRows(record, triggerStatuses), trx);
}
await this.outboxRepository.markFailed(record.id, result.error.message, trx);
});
this.errorReporter.error(result.error, { shouldBeLogged: true });
this.pushFailedToActivate(record.workflowId, result.error.message);
return;
}
case 'partial': {
await this.reportPartial(record, result.triggerStatuses);
return;
}
}
}
async reportPartial(record, triggerStatuses) {
const failures = triggerStatuses.filter((s) => s.status === 'failed');
const errorMessage = this.formatActivationError(failures);
this.logger.warn('Workflow partially published; some triggers failed to activate', {
workflowId: record.workflowId,
outboxId: record.id,
failedNodeIds: failures.map((s) => s.nodeId),
});
await this.outboxRepository.manager.transaction(async (trx) => {
await this.triggerStatusRepository.replaceForWorkflow(record.workflowId, this.toRows(record, triggerStatuses), trx);
await this.outboxRepository.markPartialSuccess(record.id, errorMessage, trx);
});
this.pushStatus({
type: 'workflowPartiallyActivated',
data: {
workflowId: record.workflowId,
activeVersionId: record.publishedVersionId,
errorMessage,
failedNodes: failures.map((triggerStatus) => ({
nodeId: triggerStatus.nodeId,
nodeName: triggerStatus.nodeName,
errorMessage: triggerStatus.errorMessage,
})),
},
});
}
toRows(record, statuses) {
return statuses.map((triggerStatus) => ({
nodeId: triggerStatus.nodeId,
versionId: record.publishedVersionId,
status: triggerStatus.status,
triggerKind: triggerStatus.triggerKind,
errorMessage: triggerStatus.status === 'failed' ? triggerStatus.errorMessage : null,
}));
}
formatActivationError(failures) {
const detail = failures
.map((status) => `"${status.nodeName}": ${status.errorMessage}`)
.join('; ');
return `Some triggers failed to activate: ${detail}`;
}
pushFailedToActivate(workflowId, errorMessage) {
this.pushStatus({
type: 'workflowFailedToActivate',
data: { workflowId, errorMessage },
});
}
pushStatus(pushMsg) {
this.push.broadcast(pushMsg);
void this.publisher
.publishCommand({ command: 'display-workflow-publication-status', payload: pushMsg })
.catch((error) => this.errorReporter.error(error, { shouldBeLogged: true }));
}
handleDisplayWorkflowPublicationStatus(pushMsg) {
this.push.broadcast(pushMsg);
}
async complete(record, triggerStatuses) {
await this.outboxRepository.manager.transaction(async (trx) => {
if (triggerStatuses !== undefined) {
await this.triggerStatusRepository.replaceForWorkflow(record.workflowId, triggerStatuses, trx);
}
await this.outboxRepository.markCompleted(record.id, trx);
});
await this.activationErrorsService.deregister(record.workflowId);
}
logSkip(record) {
const context = { workflowId: record.workflowId, outboxId: record.id };
this.logger.warn('Workflow not found, marking outbox record as completed', context);
}
};
exports.PublicationStatusReporter = PublicationStatusReporter;
__decorate([
(0, decorators_1.OnPubSubEvent)('display-workflow-publication-status', { instanceType: 'main' }),
__metadata("design:type", Function),
__metadata("design:paramtypes", [Object]),
__metadata("design:returntype", void 0)
], PublicationStatusReporter.prototype, "handleDisplayWorkflowPublicationStatus", null);
exports.PublicationStatusReporter = PublicationStatusReporter = __decorate([
(0, di_1.Service)(),
__metadata("design:paramtypes", [backend_common_1.Logger, n8n_core_1.ErrorReporter, db_1.WorkflowPublicationOutboxRepository, activation_errors_service_1.ActivationErrorsService, push_1.Push, publisher_service_1.Publisher, db_1.WorkflowPublicationTriggerStatusRepository])
], PublicationStatusReporter);
//# sourceMappingURL=publication-status-reporter.js.map