Skip to content

feat(notifications): add multi-channel notifications module (closes #158)#194

Merged
antosubash merged 6 commits into
mainfrom
feature/feat-notifications-module-multi-channel-db-sms-8cwpo
May 11, 2026
Merged

feat(notifications): add multi-channel notifications module (closes #158)#194
antosubash merged 6 commits into
mainfrom
feature/feat-notifications-module-multi-channel-db-sms-8cwpo

Conversation

@antosubash
Copy link
Copy Markdown
Owner

Summary

  • New modules/Notifications exposing INotifier.SendAsync/SendNowAsync so any module can dispatch a notification across the channels declared by INotification.Via(recipient).
  • In-tree channels: DatabaseChannel (persists Notifications_Notifications rows for the in-app inbox + outbox NotificationSentEvent), MailChannel (delegates to IEmailContracts), and a log-based LogSmsChannel as the default SMS sink that out-of-tree providers (Twilio, Slack, push) can replace.
  • Inbox page at /notifications/ with list, unread-count, mark-read, and mark-all-read endpoints, plus per-user channel opt-in settings.
  • One job per (recipient, channel) via IBackgroundJobs.EnqueueAsync<DispatchNotificationJob> so a slow channel can't block siblings.

Verification

  • Manually exercised the inbox at https://localhost:5001/notifications/ via playwright-cli:
    • Empty-state renders with 0 total · 0 unread and a disabled "Mark all read".
    • After seeding one row, the card shows the "New" badge, channel chip, type label, title, and body; counter updates to 1 total · 1 unread.
    • POST /api/notifications/{id}/read returns 204 and the UI re-renders to 1 total · 0 unread with the per-item "Mark read" button gone.
    • POST /api/notifications/read-all returns 200; GET /api/notifications/unread-count returns the live count.
  • Local CI clean: npm run check, npm run build, dotnet build, dotnet test --no-build (every module suite + Core + Generator green), and npm run test:smoke -w tests/e2e (47/47 passed).

Test plan

  • CI green on PR.
  • Reviewer spot-checks the channel-fanout policy in Notifier.SendAsync (one job per channel, JSON serialized once outside the loop) and the JSON-blob job dispatch in DispatchNotificationJob — flagged as the structural-rewrite candidate (move to IMessageBus later) in the cleanup pass.
  • Reviewer confirms the EF migration's accumulated drops are expected (matches prior per-module migration pattern; the dropped tables correspond to modules already removed from the codebase).

)

Adds modules/Notifications with INotifier for cross-module sends and a channel
fan-out pipeline backed by BackgroundJobs. In-tree channels: mail (delegates to
Email), database (persists for in-app inbox), and a log-based SMS default that
out-of-tree Twilio/Slack/push channels can replace. Per-user channel opt-ins
live in Settings; the inbox view ships an Inertia page with list, unread count,
mark-read, and mark-all-read endpoints.
Creates `Notifications_Notifications` plus the (UserId, CreatedAt, Id) and
(UserId, ReadAt) indexes that back the inbox list and unread-count queries.
Also captures accumulated model-snapshot drift from previously-removed
modules — same pattern as prior per-module migrations.
Picks up the @simplemodule/notifications workspace in package-lock.json
and reformats the generated routes.ts to match biome's line-width rule.
`outline` isn't in the Badge variant union; swap to `info` for the unread
indicator and `default` for the channel chip.
@cloudflare-workers-and-pages
Copy link
Copy Markdown

cloudflare-workers-and-pages Bot commented May 11, 2026

Deploying simplemodule-website with  Cloudflare Pages  Cloudflare Pages

Latest commit: 79c9dcf
Status: ✅  Deploy successful!
Preview URL: https://6fadbf5f.simplemodule-website.pages.dev
Branch Preview URL: https://feature-feat-notifications-m.simplemodule-website.pages.dev

View logs

@antosubash antosubash enabled auto-merge (squash) May 11, 2026 19:12
@antosubash antosubash disabled auto-merge May 11, 2026 19:13
The Dockerfile and Dockerfile.worker enumerate every module's csproj for
the dotnet restore cache layer; missing the Notifications entries broke
the docker CI check on the main image and would break the worker image
too once it gets rebuilt.
@antosubash antosubash merged commit c974f26 into main May 11, 2026
6 checks passed
@antosubash antosubash deleted the feature/feat-notifications-module-multi-channel-db-sms-8cwpo branch May 11, 2026 20:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant