System design · LLD design
Notification System
FR
1.Send a notification to a user through one or more channels - email, sms , push.
2.User have pre channel contact info & can have preferred channels
3.Notification have 2 priority levels : HIGH and NORMAL and if there is a backlog HIGH to push forward
4.High priority notifications should bypass the user preferred channels only if have a valid user contact info
5.Failed notification per channel should have a 3 attempts retry , and then marked failed if still not worked
6.Cap notification per user within a time window , but still process the priority one and skip the other notification in that window
7.Tracking notification for analytic/logging purpose
NFR
1.Scalable: system should be able to handle increase number of notifications
2.Extensible: system should be able to swap the priority logic
3.Reliability : channel failure should be isolated from each other
4.Concurrency: handle concurrent notification for a user in rate limiter counter
5. Idempotency: Safe retry for failed notifications
6.Adding different tracking notification should not affect the dispatch flow
Entities and classes
Channel enum
EMAIL , SMS , PUSH
User
-userID
-Map<Channel, string> contactInfo
-preferredchannels :Set<Channels>
getContactInfo(channel) : optional<String>
Priority enum
HIGH , NORMAL
NotificationStatus - enum
PENDING , SENT , FAILED
Notification
-notificationid
-userID
-title
-message
-priority
DeliverResult
-notificationID
-userID
-channel
-status
-attemptCount
-timestamp
NotificationChannelFactory - factory
-mapChannels <Channel, NotificationChannel> which will create a new RetryNotificationChannel
+getNotificationChannel(channel)
NotificationChannel - interface
+send(contactInfo , message) : boolean
EMAILChannel - implements NotificationChannel
+send(contactInfo , message) : boolean
SMSChannel - implements NotificationChannel
+send(contactInfo , message) : boolean
RetryNotificationChannel - implements NotificationChannel - the decorator
-attempCount;
+send(contactInfo , message) : boolean 3 time retry if pass return true else false
+getAttemptCount()
NotificationObserver - interface
+onResult(DeliverResult result)
NotificationService
-factory NotificationChannelFactory
-List<NotificationObserver> observers
RateLimiter ratelimiter
+notificationDispatcher(notification, user )
exceedlimit(userid) ? return
getContactInfo()
{
// find the notificationchannel from factory
// send
// record - success ? then SENT : FAILED
// add to observer
}
+priorirtiseListOfNotification(List<Notification> notification )
Use priority queue (PriorityBlockingQueue) for publishing first notification for high priority