-
Notifications
You must be signed in to change notification settings - Fork 1
features notifications
Active contributors: Saksham, Ravi
The notifications system is a multi-channel dispatch pipeline that delivers push (FCM), email, SMS, and in-app notifications. A central type registry in notification_config.py declares every notification type with its category, priority, allowed channels, TTL, and frequency cap; the dispatcher computes the effective channel set per user based on their notification_settings JSON; and a shared APScheduler job fires daily marketing pushes.
app/services/
├── notification_config.py # NOTIFICATION_TYPES registry + config dataclasses
├── notification_dispatcher.py # dispatch_notification_to_user + segment dispatch
├── notification_scheduler.py # daily marketing push cron registration
├── push_notification.py # flatmates-specific push helpers
├── email.py # send_email (SMTP/transactional provider)
├── sms.py # send_sms (SMS gateway)
└── notifications/
├── __init__.py # re-exports crud, fcm, helpers, push
├── crud.py # _record_notification, list_notifications_for_user, mark_opened
├── fcm.py # FCM access token, build_message, send_message
├── helpers.py # _NOTIFICATION_EXECUTOR thread pool, _supa client, _augment_data_with_meta
└── push.py # register_device_token, send_to_user, send_to_token, send_to_topic, send_bulk
app/api/api_v1/endpoints/
└── notifications.py # list, mark read, register/unregister device token
| Abstraction | File | Role |
|---|---|---|
NOTIFICATION_TYPES |
app/services/notification_config.py |
Dict of NotificationTypeConfig keyed by type string |
NotificationTypeConfig |
app/services/notification_config.py |
key, category, priority, allowed_channels, default_ttl_seconds, frequency_cap, marketing_opt_in_key |
NotificationChannel |
app/services/notification_config.py |
Enum: in_app, push, email, sms
|
NotificationCategory |
app/services/notification_config.py |
Enum: transactional, system, marketing
|
FrequencyCap |
app/services/notification_config.py |
per_day, per_week caps per user per type |
dispatch_notification_to_user |
app/services/notification_dispatcher.py |
Single-user dispatch: resolves channels, sends, records |
_get_user_channels_from_settings |
app/services/notification_dispatcher.py |
Computes effective channel set from users.notification_settings JSON |
send_to_user / send_to_topic / send_bulk
|
app/services/notifications/push.py |
FCM push dispatch via Supabase push API |
_access_token / build_message / send_message
|
app/services/notifications/fcm.py |
FCM OAuth2 token + message construction + HTTP send |
_record_notification |
app/services/notifications/crud.py |
Persists in-app notification row |
register_device_token / unregister_device_token
|
app/services/notifications/push.py |
Device token lifecycle |
_NOTIFICATION_EXECUTOR |
app/services/notifications/helpers.py |
Thread pool for non-blocking sends |
The type registry is the source of truth. NOTIFICATION_TYPES maps each logical type (e.g. booking_confirmed, payment_failed, chat_message, password_changed, security_alert) to a NotificationTypeConfig with its category (transactional, system, marketing), priority (low, normal, high, critical), allowed channels, default TTL, and optional FrequencyCap and marketing_opt_in_key. Adding a new notification type requires an entry here — the AGENTS.md rules make this explicit.
Dispatch flows through dispatch_notification_to_user. It looks up the NotificationTypeConfig, calls _get_user_channels_from_settings to intersect the type's allowed_channels with the user's notification_settings JSON (global push_notifications, email_notifications, sms_notifications toggles plus marketing-specific promotional_emails / promotional_push / categories.promotions flags and optional per-type opt-in keys). The in-app channel is always enabled. For each resulting channel, the dispatcher calls send_email, send_sms, or the push pipeline, and always records an in-app notification row via _record_notification.
graph TD
Service[app/services/* event] --> DISP[dispatch_notification_to_user]
DISP --> CFG[NOTIFICATION_TYPES type lookup]
CFG --> CH[_get_user_channels_from_settings]
CH -->|users.notification_settings JSON| SET{effective channels}
SET -->|push| FCM[notifications.push.send_to_user]
SET -->|email| EMAIL[email.send_email]
SET -->|sms| SMS[sms.send_sms]
SET -->|in_app always| CRUD[notifications.crud._record_notification]
FCM --> SUPA[Supabase push API]
SUPA --> FCM_API[(FCM HTTP v1)]
FCM_API --> Device[User device]
Sched[AsyncIOScheduler 09:00 daily] -->|ENABLE_NOTIF_SCHEDULER| MKT[send_to_topic marketing]
MKT --> SUPA
Flat[flatmates events] --> PUSH[push_notification.py]
PUSH --> DISP
PUSH --> SSE[sse_bus.emit new_notification]
Client -->|GET /notifications| EP[app/api/.../notifications.py]
EP --> List[list_notifications_for_user]
Client -->|POST /notifications/device-token| REG[register_device_token]
Push uses Firebase Cloud Messaging through Supabase's push API. notifications/fcm.py mints an OAuth2 access token for the FCM_SCOPE using the Firebase service account credentials (_fcm_credentials, _fcm_token_expiry), build_message constructs the FCM HTTP v1 message, and send_message performs the HTTP send. push.py exposes send_to_user (resolves device tokens for the user), send_to_token (direct), send_to_topic (broadcast), and send_bulk (batch). Device tokens are registered and unregistered through the /api/v1/notifications/device-token endpoint.
The flatmates module has its own thin push helper in push_notification.py that wraps dispatch_notification_to_user for flatmates events (new_match, new_message, listing approved, visit scheduled/confirmed) and always emits an SSE new_notification event to the user's SSE bus queue, falling back to a log-only stub if the dispatcher is unavailable.
The scheduler in notification_scheduler.py registers a daily 09:00 marketing push job on the shared AsyncIOScheduler if ENABLE_NOTIF_SCHEDULER is true. It calls send_to_topic("marketing", ...) with a promotion_generic type key. In serverless mode the scheduler is skipped.
-
Type registry contract: every new notification type must be added to
NOTIFICATION_TYPESinnotification_config.pyper AGENTS.md. -
SSE bus: push dispatch also emits
new_notificationevents throughapp/core/sse.pyfor real-time in-app delivery. -
User settings:
users.notification_settingsJSON drives per-user channel selection; the dispatcher tolerates both 360 Ghar and Stays app shapes. -
Schedulers: the marketing push job registers on the shared
AsyncIOScheduler(see infrastructure). -
Supabase: FCM dispatch goes through the Supabase push API; the
_supahelper innotifications/helpers.pyprovides the client. -
Flatmates:
app/services/push_notification.pyis the flatmates-specific entry point. -
Bookings:
app/api/api_v1/endpoints/bookings.pycallsdispatch_notification_to_userdirectly forbooking_confirmedand related events.
Add a new notification type by registering it in NOTIFICATION_TYPES (with category, priority, allowed channels, TTL, optional frequency cap and marketing opt-in key), then calling dispatch_notification_to_user from the service method after the DB commit. New channels require extending NotificationChannel, the dispatcher's send switch, and _get_user_channels_from_settings. Frequency cap enforcement belongs in the dispatcher before send. Update CLAUDE.md and AGENTS.md when adding types or channels.
| File | Purpose |
|---|---|
app/services/notification_config.py |
Type registry + config dataclasses (364 lines) |
app/services/notification_dispatcher.py |
Multi-channel dispatch (284 lines) |
app/services/notification_scheduler.py |
Daily marketing push cron |
app/services/notifications/crud.py |
In-app notification CRUD |
app/services/notifications/fcm.py |
FCM token + message + send |
app/services/notifications/push.py |
Supabase push dispatch + device tokens (11.8 KB) |
app/services/notifications/helpers.py |
Thread pool, Supabase client, type config lookup |
app/services/push_notification.py |
Flatmates push helpers (239 lines) |
app/services/email.py |
Email send |
app/services/sms.py |
SMS send |
app/api/api_v1/endpoints/notifications.py |
Notification REST endpoints (11.5 KB) |
- Features overview
- Ghar Core (marketplace)
- 360 Stays (bookings)
- 360 Flatmates
- Property Management
- 360 Virtual Tours
- 360 Data Hub
- MCP servers and widgets
- AI agent
- Blog and SEO
- Notifications
- Vastu analyzer