Skip to content

feat(messaging): ADR-0030 P3b-1 — quiet-hours (deferred dispatch)#1453

Merged
os-zhuang merged 1 commit into
mainfrom
claude/adr-0030-p3b
Jun 1, 2026
Merged

feat(messaging): ADR-0030 P3b-1 — quiet-hours (deferred dispatch)#1453
os-zhuang merged 1 commit into
mainfrom
claude/adr-0030-p3b

Conversation

@os-zhuang
Copy link
Copy Markdown
Contributor

Summary

Implements ADR-0030 P3b-1 — quiet-hours, continuing from merged P0–P3a. A notification that lands inside a recipient's quiet-hours window is deferred to the window's end instead of disturbing them; it then delivers normally.

P3b is split: P3b-1 (this PR) = quiet-hours (deferral); P3b-2 (next) = digest (window collapse), which builds on the same deferral foundation.

What changed (the elegant bit: reuse the P1 outbox)

No new scheduler, no parallel table — quiet-hours is a deferred dispatch on the existing outbox:

  • EnqueueDeliveryInput.notBefore → the delivery row's initial nextAttemptAt. The P1 dispatcher already skips pending rows whose nextAttemptAt is in the future (memory-outbox/sql-outbox claim both check this), so the row simply isn't claimed until the window ends. One delivery spine, reusing claim / retry / dead-letter / observability.
  • PreferenceResolver reads quiet_hours ({ tz, start, end } — P2's field) off a channel-wildcard preference row (quiet hours are a per-person, channel-agnostic setting), computes the deferral with quietHoursDeferral() (HH:MM in the row's tz, default UTC; overnight windows that wrap midnight supported; uses Intl for the tz wall-clock), and stamps notBefore on the target. emit() passes it through to enqueue.
  • critical severity bypasses quiet hours (delivers immediately), mirroring how mandatory topics bypass muting. Honored on the durable outbox path; inline best-effort fan-out ignores it (quiet-hours needs the outbox).

Acceptance

  • ✅ A notification inside the quiet-hours window is deferred to the window end (observable as the delivery row's next_attempt_at); outside the window it sends immediately; critical bypasses.

Testing

service-messaging: 92 passing — adds quietHoursDeferral unit cases (same-day / overnight-wrap / outside / degenerate / bad input) and resolver cases (notBefore stamped on target, critical bypass, JSON-string quiet_hours).

Follow-ups

  • P3b-2 — digest: enqueue digest items deferred to the window, then a collapse step merges same-(user, channel, window) rows into one materialization at window time (needs a digest_key on the delivery row + a digest assembler + a digest render template). Consumes P2's digest field. Completes the ADR-0030 build spec.
  • tz fallback to a sys_user timezone field (currently quiet_hours.tz → UTC).
  • Still pending from P0: objectui bell cut-over + mark-read receipt write.

🤖 Generated with Claude Code


Generated by Claude Code

A notification landing inside a recipient's quiet-hours window is deferred to
the window's end instead of disturbing them, then delivers normally.

- Implemented as deferred dispatch on the P1 outbox (no parallel scheduler):
  EnqueueDeliveryInput.notBefore → the delivery row's initial nextAttemptAt;
  the dispatcher already skips pending rows whose nextAttemptAt is in the future.
- PreferenceResolver reads quiet_hours ({tz,start,end}, P2's field) off a
  channel-wildcard preference row (quiet hours are per-person, channel-agnostic),
  computes the deferral via quietHoursDeferral() (HH:MM in tz, default UTC,
  overnight windows supported), and stamps notBefore on the target; emit() passes
  it to the outbox.
- critical severity bypasses quiet hours (delivers immediately). Honored on the
  durable outbox path; inline fan-out ignores it.

Tests: service-messaging 92 passing (quietHoursDeferral unit cases + resolver
notBefore/critical-bypass/JSON-string cases).

Follow-up: P3b-2 digest (window collapse) builds on this deferral foundation.

https://claude.ai/code/session_015pRGvrm3zrk5m8YvZhkAmF
@vercel
Copy link
Copy Markdown

vercel Bot commented Jun 1, 2026

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

Project Deployment Actions Updated (UTC)
spec Ready Ready Preview, Comment Jun 1, 2026 7:08am

Request Review

@os-zhuang os-zhuang marked this pull request as ready for review June 1, 2026 07:06
@github-actions github-actions Bot added documentation Improvements or additions to documentation tests tooling size/m labels Jun 1, 2026
@os-zhuang os-zhuang merged commit c8753ef into main Jun 1, 2026
12 checks passed
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/m tests tooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants