91 lines
5.5 KiB
Markdown
91 lines
5.5 KiB
Markdown
# Proposal: Notification System Redesign
|
||
|
||
## Intent
|
||
|
||
The current notification system has three critical limitations: (1) notifications are sent synchronously during appointment lifecycle operations, blocking the API response; (2) the notification-sender worker only handles today's appointments with a global delay (no per-company throttling for WhatsApp rate limits); and (3) there are no per-company or per-client notification preferences — notifications are either on or off for the entire company. This redesign decouples notification delivery from business operations into a job-based, multi-channel, policy-driven system.
|
||
|
||
## Scope
|
||
|
||
### In Scope
|
||
- New `NotificationJob` model: per-notification job records with status, channel, payload, retry state
|
||
- New `CompanyNotificationPolicy` model: org-level defaults for channels, scheduling windows, WhatsApp throttle config
|
||
- New `ClientNotificationPreferences` model: per-client opt-in/out per channel
|
||
- New `ClientCompanyNotificationOverride` model: per-client per-org overrides
|
||
- Policy resolution engine: Plan limits → Org override → Client prefs → Org default → System default
|
||
- Redesigned notification-sender worker: MongoDB polling, per-company WhatsApp throttle (8–16s), multi-channel dispatch
|
||
- Server integration: replace inline notification calls in `Appointments` with job creation
|
||
- Multi-channel support: WhatsApp (Baileys), Email (DonWeb), System (in-app + Socket.IO)
|
||
|
||
### Out of Scope
|
||
- SMS channel (plan feature exists but not implemented today)
|
||
- Notification templates / content builder
|
||
- Client-facing notification preferences UI
|
||
- Notification analytics / delivery reports
|
||
- Push notifications (mobile)
|
||
- Batch notification operations (e.g., "notify all clients about holiday")
|
||
|
||
## Capabilities
|
||
|
||
### New Capabilities
|
||
- `notification-jobs`: Job creation, status tracking, retry logic, and lifecycle management for notification delivery
|
||
- `notification-policies`: Company and client notification preferences, policy resolution hierarchy, channel configuration
|
||
- `notification-worker`: Multi-channel job processor with per-company throttling and MongoDB polling
|
||
- `notification-integration`: Server-side hooks that create notification jobs from appointment lifecycle events
|
||
|
||
### Modified Capabilities
|
||
None — no existing specs in `openspec/specs/`.
|
||
|
||
## Approach
|
||
|
||
**Server (job creation):** Replace inline `NotificationsManager.send*()` calls in `Appointments.ts` with `NotificationJobService.createJob()`. The service resolves the effective policy, checks plan limits, and persists a `NotificationJob` document. This makes API calls non-blocking.
|
||
|
||
**notification-sender (worker):** Poll MongoDB for `status: "pending"` jobs. Process per-company with configurable WhatsApp throttle (default 8–16s between messages for same company). Email and System channels have no throttle. Failed jobs retry up to 3x with exponential backoff.
|
||
|
||
**Policy resolution:** Resolve in order: Plan feature flags → `ClientCompanyNotificationOverride` (per-client per-org) → `ClientNotificationPreferences` (client global) → `CompanyNotificationPolicy` (org default) → System defaults (all channels on).
|
||
|
||
**Migration:** No data migration needed — no pending notifications exist. New models are additive.
|
||
|
||
## Affected Areas
|
||
|
||
| Area | Impact | Description |
|
||
|------|--------|-------------|
|
||
| `notification-sender/src/` | New | Complete rewrite: job polling, multi-channel dispatch, throttle |
|
||
| `server/src/Models/Notifications/` | Modified | Add job creation service; existing adapters remain for direct sends |
|
||
| `server/src/Models/Appointments/Appointments.ts` | Modified | Replace inline sends with job creation calls |
|
||
| `server/src/Models/Plans/Plans.interface.ts` | Unchanged | Plan features already define channel support |
|
||
| New: `server/src/Models/NotificationJobs/` | New | NotificationJob model + adapter |
|
||
| New: `server/src/Models/NotificationPolicies/` | New | Company/Client policy models + resolution engine |
|
||
| New: `notification-sender/src/Models/Jobs/` | New | Job polling model for worker |
|
||
|
||
## Risks
|
||
|
||
| Risk | Likelihood | Mitigation |
|
||
|------|------------|------------|
|
||
| WhatsApp rate limit hit during high-volume periods | High | Per-company throttle (8–16s), exponential backoff on failures |
|
||
| Job queue grows faster than worker processes | Medium | Monitor queue depth; add alerting on backlog threshold |
|
||
| Policy resolution adds latency to appointment creation | Low | Resolution is a simple DB query cascade; cache per-request |
|
||
| Breaking existing notification behavior during transition | Medium | Feature flag: keep inline sends as fallback during rollout |
|
||
|
||
## Rollback Plan
|
||
|
||
1. Disable job creation in server via feature flag (reverts to inline sends)
|
||
2. Stop notification-sender worker
|
||
3. Existing inline notification paths remain unchanged — no code removal needed until stable
|
||
4. Job collection can be truncated without data loss (jobs are ephemeral)
|
||
|
||
## Dependencies
|
||
|
||
- MongoDB (shared across all modules) — already available
|
||
- Baileys (txbot) — existing WhatsApp integration, no changes needed
|
||
- DonWeb email API — existing integration, no changes needed
|
||
- Socket.IO — existing in server, no changes needed
|
||
|
||
## Success Criteria
|
||
|
||
- [ ] Appointment creation/update/delete returns within normal latency (< 200ms)
|
||
- [ ] WhatsApp messages for same company spaced ≥ 8s apart
|
||
- [ ] Failed notifications retry up to 3x with exponential backoff
|
||
- [ ] Policy resolution correctly cascades through hierarchy
|
||
- [ ] Zero missed notifications during 24h soak test
|
||
- [ ] notification-sender processes backlog within 5 minutes under normal load
|