454. Design Extensible Notification System for Sending Alerts
Asked in
Design Extensible Notification System for Sending Alerts

Design an in-memory alerting platform that supports different alert categories and sends each alert through one or more delivery channels.

The platform initially supports configured categories and channels such as EMAIL, SMS, and PUSH. New alert categories and delivery channels must be registerable without changing the existing public method signatures.

Class

AlertingPlatform

Constructor

public AlertingPlatform( List<String> alertCategories, List<String> deliveryChannels)

  • alertCategories contains the initially supported alert categories.
  • deliveryChannels contains the initially supported delivery channels.
  • The order of deliveryChannels defines the channel order used in returned notification logs.

Methods

registerAlertCategory

public boolean registerAlertCategory( String alertCategory)

  • Registers a new supported alert category.
  • Returns true when the category is newly registered.
  • Returns false when the category is blank or already registered.

registerDeliveryChannel

public boolean registerDeliveryChannel( String deliveryChannel)

  • Registers a new supported delivery channel.
  • Returns true when the channel is newly registered.
  • Returns false when the channel is blank or already registered.
  • A newly registered channel is placed after all previously registered channels in the platform's channel order.

sendAlert

public List<String> sendAlert( String alertId, String alertCategory, String message, List<String> recipientIds, List<String> deliveryChannels)

  • alertId uniquely identifies the alert.
  • alertCategory identifies the registered category of the alert.
  • message contains the alert text.
  • recipientIds contains the recipients who must receive the alert.
  • deliveryChannels contains the registered channels through which the alert must be sent.
  • Returns one notification log for every unique recipient and requested channel combination.
  • Returns an empty list if the alert ID was used successfully before or any input is invalid.

Alert Rules

  • Alert category and delivery channel names are case-sensitive.
  • Every alert category and requested delivery channel must already be registered.
  • Duplicate recipient IDs are ignored after their first occurrence.
  • Duplicate requested delivery channels are ignored.
  • Recipients are processed in the order of their first occurrence in recipientIds.
  • For each recipient, channels are processed in the platform's registered channel order, regardless of their order in the method input.
  • A successfully used alertId cannot be used for another alert.
  • Invalid calls must not reserve the supplied alertId or otherwise modify the platform.
  • Recipient contact information and channel-specific routing details are assumed to be available outside this problem.
  • Actual communication with external Email, SMS, Push, or other providers is outside the problem scope. Returned logs represent successful dispatch requests.

Output Format

Each generated notification must use this format:

ALERT - alertId=<alertId> - category=<alertCategory> - recipientId=<recipientId> - channel=<deliveryChannel> - message="<message>"

Constraints

  • 1 ≤ alertCategories.size() ≤ 1,000
  • 1 ≤ deliveryChannels.size() ≤ 100
  • 1 ≤ recipientIds.size() ≤ 1,000
  • 1 ≤ deliveryChannels.size() ≤ 100 for each sendAlert call.
  • At most 100,000 alerts are successfully sent.
  • At most 10,000 alert categories are registered.
  • At most 1,000 delivery channels are registered.
  • Identifiers, categories, and channel names contain between 1 and 100 characters.
  • 1 ≤ message.length() ≤ 500
  • The message does not contain a double quotation mark.
  • All parameters, lists, and list elements are non-null.
  • All string values required by a successful operation are non-blank.
  • The constructor lists contain distinct categories and distinct channels.

Examples

Example 1

AlertingPlatform( alertCategories = List.of("SECURITY", "PAYMENT", "SERVICE"), deliveryChannels = List.of("EMAIL", "SMS", "PUSH"))

sendAlert( alertId = "ALERT-104", alertCategory = "SECURITY", message = "A new device signed in", recipientIds = List.of("USER-8", "USER-3"), deliveryChannels = List.of("PUSH", "SMS"))

Output: List.of( "ALERT - alertId=ALERT-104 - category=SECURITY - recipientId=USER-8 - channel=SMS - message="A new device signed in"", "ALERT - alertId=ALERT-104 - category=SECURITY - recipientId=USER-8 - channel=PUSH - message="A new device signed in"", "ALERT - alertId=ALERT-104 - category=SECURITY - recipientId=USER-3 - channel=SMS - message="A new device signed in"", "ALERT - alertId=ALERT-104 - category=SECURITY - recipientId=USER-3 - channel=PUSH - message="A new device signed in"")

Both recipients receive the alert through SMS and PUSH. Although PUSH appears first in the method input, SMS precedes it in the platform's channel order.

Example 2

AlertingPlatform( alertCategories = List.of("ACCOUNT"), deliveryChannels = List.of("EMAIL", "SMS"))

registerAlertCategory( alertCategory = "MAINTENANCE")

Output: true

registerDeliveryChannel( deliveryChannel = "VOICE")

Output: true

sendAlert( alertId = "ALERT-205", alertCategory = "MAINTENANCE", message = "Planned maintenance starts at midnight", recipientIds = List.of("USER-21"), deliveryChannels = List.of("VOICE", "EMAIL"))

Output: List.of( "ALERT - alertId=ALERT-205 - category=MAINTENANCE - recipientId=USER-21 - channel=EMAIL - message="Planned maintenance starts at midnight"", "ALERT - alertId=ALERT-205 - category=MAINTENANCE - recipientId=USER-21 - channel=VOICE - message="Planned maintenance starts at midnight"")

The newly registered category and channel can be used without changing any existing public method. EMAIL appears before VOICE because it was registered earlier.

Example 3

AlertingPlatform( alertCategories = List.of("PAYMENT"), deliveryChannels = List.of("EMAIL", "SMS", "PUSH"))

sendAlert( alertId = "ALERT-309", alertCategory = "PAYMENT", message = "Your payment was completed", recipientIds = List.of("USER-5", "USER-5"), deliveryChannels = List.of("SMS", "SMS"))

Output: List.of( "ALERT - alertId=ALERT-309 - category=PAYMENT - recipientId=USER-5 - channel=SMS - message="Your payment was completed"")

Duplicate recipient IDs and duplicate channels generate only one notification for the unique recipient-channel combination.

sendAlert( alertId = "ALERT-309", alertCategory = "PAYMENT", message = "A second payment message", recipientIds = List.of("USER-9"), deliveryChannels = List.of("EMAIL"))

Output: List.of()

The alert ID was already used successfully, so it cannot be used again.



Please use Laptop/Desktop or any other large screen to add/edit code.