feat: add configurable notification dispatch retries (#1655)

* feat: add configurable notification dispatch retries

Allow each node to set 0-3 extra in-process delivery attempts with a fixed
one-second delay for routes, agents, and Test dispatch.

* fix: harden notification retry settings load/save and channel tests

Guard Delivery retries against failed and out-of-order same-node settings responses, and cover Slack/webhook retry classification alongside Discord.

* fix: clear Delivery retries saving state and correct screenshot alt

Separate save-request ownership from value-generation invalidation so a successful PATCH cannot leave Save retries stuck on Saving, reset saving on node switch, and align the Channels screenshot alt with the committed image.

* fix: surface invalid notification retry settings instead of false saved clamp

Align Channels GET handling with the backend strict 0-3 parser so stored values like 9 or 1.5 show as error needing repair, matching runtime fallback to 0 instead of displaying a clamped saved policy.
This commit is contained in:
Anso
2026-07-20 20:29:17 -04:00
committed by GitHub
parent 859839082c
commit 090a0d73ac
19 changed files with 1175 additions and 38 deletions
@@ -0,0 +1,21 @@
import { describe, it, expect } from 'vitest';
import { parseNotificationDispatchRetries } from './notificationDispatchRetries';
describe('parseNotificationDispatchRetries', () => {
it('accepts integers and digit strings 0-3', () => {
expect(parseNotificationDispatchRetries(0)).toBe(0);
expect(parseNotificationDispatchRetries(3)).toBe(3);
expect(parseNotificationDispatchRetries('2')).toBe(2);
});
it('rejects out-of-range, decimals, and non-canonical strings', () => {
expect(parseNotificationDispatchRetries(9)).toBeNull();
expect(parseNotificationDispatchRetries('9')).toBeNull();
expect(parseNotificationDispatchRetries(1.5)).toBeNull();
expect(parseNotificationDispatchRetries('1.5')).toBeNull();
expect(parseNotificationDispatchRetries(' 1')).toBeNull();
expect(parseNotificationDispatchRetries(null)).toBeNull();
expect(parseNotificationDispatchRetries(true)).toBeNull();
});
});
@@ -0,0 +1,16 @@
/**
* Strict parser for notification_dispatch_retries (extra attempts, 0..3).
* Must stay aligned with backend/src/helpers/notificationDispatchRetries.ts:
* accepts JSON number integers or single-digit strings "0".."3" only.
*/
export function parseNotificationDispatchRetries(raw: unknown): number | null {
if (typeof raw === 'number') {
if (!Number.isInteger(raw) || raw < 0 || raw > 3) return null;
return raw;
}
if (typeof raw === 'string') {
if (!/^[0-3]$/.test(raw)) return null;
return Number(raw);
}
return null;
}