mirror of
https://github.com/n8n-io/n8n.git
synced 2026-10-17 21:49:36 +02:00
chore: Extract the duplicated per-node failure message formatter in the workflow publication service (#37673)
Co-authored-by: n8n-cat-bot[bot] <n8n-cat-bot[bot]@users.noreply.github.com> Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
11289ced77
commit
ffe97a82e7
|
|
@ -0,0 +1,22 @@
|
|||
import { formatNodeFailures } from '@/workflows/publication/format-node-failures';
|
||||
|
||||
describe('formatNodeFailures', () => {
|
||||
test('returns an empty string for no failures', () => {
|
||||
expect(formatNodeFailures([])).toBe('');
|
||||
});
|
||||
|
||||
test('quotes the node name and appends the message', () => {
|
||||
expect(formatNodeFailures([{ nodeName: 'Webhook', message: 'port in use' }])).toBe(
|
||||
'"Webhook": port in use',
|
||||
);
|
||||
});
|
||||
|
||||
test('joins multiple failures with a semicolon', () => {
|
||||
expect(
|
||||
formatNodeFailures([
|
||||
{ nodeName: 'Webhook', message: 'port in use' },
|
||||
{ nodeName: 'Schedule Trigger', message: 'bad cron' },
|
||||
]),
|
||||
).toBe('"Webhook": port in use; "Schedule Trigger": bad cron');
|
||||
});
|
||||
});
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
/** Formats per-node failures as `"NodeName": message`, joined with `; `. Callers add the prefix. */
|
||||
export function formatNodeFailures(failures: Array<{ nodeName: string; message: string }>): string {
|
||||
return failures.map(({ nodeName, message }) => `"${nodeName}": ${message}`).join('; ');
|
||||
}
|
||||
|
|
@ -14,6 +14,7 @@ import { OperationalError } from 'n8n-workflow';
|
|||
import { ActivationErrorsService } from '@/activation-errors.service';
|
||||
import { isPolicyRefusal } from '@/policy/policy-violation.error';
|
||||
import { Publisher } from '@/scaling/pubsub/publisher.service';
|
||||
import { formatNodeFailures } from '@/workflows/publication/format-node-failures';
|
||||
import type {
|
||||
FailedTriggerPublicationStatus,
|
||||
PublicationResult,
|
||||
|
|
@ -183,9 +184,9 @@ export class PublicationStatusReporter {
|
|||
|
||||
/** Builds a human-readable message naming each failed node and its error. */
|
||||
private formatActivationError(failures: FailedTriggerPublicationStatus[]): string {
|
||||
const detail = failures
|
||||
.map((status) => `"${status.nodeName}": ${status.errorMessage}`)
|
||||
.join('; ');
|
||||
const detail = formatNodeFailures(
|
||||
failures.map(({ nodeName, errorMessage }) => ({ nodeName, message: errorMessage })),
|
||||
);
|
||||
|
||||
return `Some triggers failed to activate: ${detail}`;
|
||||
}
|
||||
|
|
@ -236,9 +237,9 @@ export class PublicationStatusReporter {
|
|||
): string | undefined {
|
||||
if (!teardownFailures?.length) return undefined;
|
||||
|
||||
const detail = teardownFailures
|
||||
.map((failure) => `"${failure.nodeName}": ${failure.error.message}`)
|
||||
.join('; ');
|
||||
const detail = formatNodeFailures(
|
||||
teardownFailures.map(({ nodeName, error }) => ({ nodeName, message: error.message })),
|
||||
);
|
||||
const message = `External webhook deregistration failed for: ${detail}`;
|
||||
|
||||
this.errorReporter.error(
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ import { DurableJobProvisioner } from '@/scheduling/durable-job-provisioner';
|
|||
import { WorkflowScheduledJobOwner } from '@/scheduling/workflow-scheduled-job-owner';
|
||||
import { OwnershipService } from '@/services/ownership.service';
|
||||
import { Telemetry } from '@/telemetry';
|
||||
import { formatNodeFailures } from '@/workflows/publication/format-node-failures';
|
||||
import { healNodeIds } from '@/workflows/publication/heal-node-ids';
|
||||
import type {
|
||||
PublicationResult,
|
||||
|
|
@ -440,9 +441,9 @@ export class WorkflowPublicationApplier {
|
|||
private toActivationError(failures: TriggerActivationFailure[]): Error {
|
||||
if (failures.length === 1) return failures[0].error;
|
||||
|
||||
const detail = failures
|
||||
.map((failure) => `"${failure.nodeName}": ${failure.error.message}`)
|
||||
.join('; ');
|
||||
const detail = formatNodeFailures(
|
||||
failures.map(({ nodeName, error }) => ({ nodeName, message: error.message })),
|
||||
);
|
||||
|
||||
return new Error(`Triggers failed to activate: ${detail}`);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user