2.6 KiB
digest-channel — Digest delivery channel
(no submodules)
Purpose
digest-channel.ts ships the DigestChannel implementation that batches notifications into periodic summaries delivered through a delegate DeliveryChannel. It is the channel-shape adapter for "weekly summary email" / "hourly Slack roll-up" / "daily push digest" use-cases — it implements DeliveryChannel so it slots into the router exactly like a direct channel, and it owns its own per-recipient queue.
Features
- Wraps any
DeliveryChannelasdelegate. - Per-recipient FIFO queue with configurable
maxPerDigestcap. intervalMsgates the next flush —sendopportunistically flushes when the interval has elapsed since the last flush.- Customisable
formatDigest(notifications)formatter. flush(recipient),flushAll(),queueSize,pendingRecipientsfor ops/cron integrations.- Injectable
Clockso tests advance the interval without sleeping.
Usage: Basic
import { DigestChannel, EmailChannel } from "@suaveplan/notification-channel";
const email = new EmailChannel({ from: "noreply@x", sendFn });
const digest = new DigestChannel({
delegate: email,
intervalMs: 3_600_000,
});
await digest.send(notification);
Usage: Advanced
const digest = new DigestChannel({
delegate: email,
intervalMs: 86_400_000,
maxPerDigest: 25,
formatDigest: (ns) =>
ns.map((n, i) => `${i + 1}. [${n.priority}] ${n.subject}: ${n.body}`).join("\n"),
clock: () => Date.now(),
});
// In a cron handler:
const results = await digest.flushAll();
API Reference
DigestChannel(config: DigestChannelConfig)— constructor.DigestChannelConfig—{ delegate, intervalMs?, maxPerDigest?, formatDigest?, clock? }.enqueue(n),send(n),flush(recipient),flushAll(),queueSize(recipient),pendingRecipients(),canSend(n).
Implementation Notes
enqueue silently drops the overflow when the queue reaches maxPerDigest. This is a deliberate denial-of-service shield — a runaway pipeline cannot blow memory by enqueuing forever. The default formatter numbers entries and labels them by subject; consumers wanting Markdown / HTML output supply their own formatDigest. canSend proxies to the delegate, so the digest channel inherits the delegate's recipient validation — useful when the delegate is an EmailChannel that wants @-only recipients. lastFlush is tracked per-recipient and consulted from send/flushAll; a recipient flushed seconds ago will not flush again until the interval has elapsed.