Skip to content

feat(messaging): digest batching for notifications (ADR-0030 P3b-2)#1582

Merged
xuyushun441-sys merged 1 commit into
mainfrom
feat/notification-digest
Jun 4, 2026
Merged

feat(messaging): digest batching for notifications (ADR-0030 P3b-2)#1582
xuyushun441-sys merged 1 commit into
mainfrom
feat/notification-digest

Conversation

@xuyushun441-sys
Copy link
Copy Markdown
Contributor

Completes ADR-0030 P3b-2 — the digest middleware the platform declared in P2 (sys_notification_preference.digest) but never consumed.

What

Recipients can batch a topic into a daily / weekly digest instead of getting every notification immediately. Builds directly on P3b-1's deferral seam.

  • PreferenceResolver now reads the digest field. digestDeferral() defers a batched recipient to the next window (local midnight for daily, Monday 00:00 for weekly) and tags the target with a stable window label. Digest takes precedence over quiet-hours; critical and mandatory topics bypass it entirely.
  • sys_notification_delivery gains digest_key (recipient|channel|window) + a grouping index. Batched rows partition by that key so a window's rows co-locate in one partition; the normal outbox claim() skips them and a new claimDigest() drains a window whole (implemented in both memory + sql outbox).
  • Dispatcher digest pass: under the existing per-partition cluster lock, it claims due batched rows, groups by digest_key, and collapses each (recipient, channel, window) group into one renderDigest() message, then acks every row in the group with that single outcome (failure re-defers the whole group).

Partition-by-digest_key + the existing lock means exactly one node assembles each digest — no double-send across a cluster.

Scope

Additive: non-digest notifications are completely unchanged. Deferred follow-ups (noted in the ADR): timezone fallback to a sys_user field (windows currently use quiet_hours.tz → UTC), a configurable daily send-hour, and MJML digest emails.

Tests

+13 (127 total in service-messaging): digestDeferral daily/weekly + tz; resolver stamps window + precedence + critical bypass; renderDigest collapse; outbox claim/claimDigest separation + window deferral; end-to-end dispatcher collapse (3 rows → 1 message, all acked) + group re-defer on failure.

🤖 Generated with Claude Code

Recipients can batch a topic into a daily/weekly digest instead of receiving
every notification immediately. Builds on P3b-1's deferral seam:

- PreferenceResolver consumes the `digest` field; digestDeferral() defers a
  batched recipient to the next window (local midnight / Monday 00:00) and tags
  the target with a stable window. Digest takes precedence over quiet-hours;
  critical + mandatory topics bypass it.
- sys_notification_delivery gains digest_key (recipient|channel|window). Batched
  rows partition by that key so a window co-locates; normal claim() skips them and
  the new claimDigest() drains a window whole (memory + sql outbox).
- The dispatcher's digest pass collapses each (recipient, channel, window) group
  into one renderDigest() message under the per-partition lock, then acks every
  row in the group with that single outcome.

Additive — non-digest delivery is unchanged. +13 tests (127 total). tz-from-
sys_user, configurable send-hour, and MJML digest emails are deferred follow-ups.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@vercel
Copy link
Copy Markdown

vercel Bot commented Jun 4, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
spec Ready Ready Preview, Comment Jun 4, 2026 2:21pm

Request Review

@github-actions github-actions Bot added documentation Improvements or additions to documentation tests tooling size/l labels Jun 4, 2026
@xuyushun441-sys xuyushun441-sys merged commit 9f311f8 into main Jun 4, 2026
12 checks passed
@xuyushun441-sys xuyushun441-sys deleted the feat/notification-digest branch June 4, 2026 14:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation size/l tests tooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants