Multi-Channel Notification System
Overview
The Multi-Channel Notification System is a comprehensive solution for delivering notifications across multiple communication channels (Email, SMS, WhatsApp, Telegram, and FCM). It provides a unified interface for sending notifications while respecting user preferences, Do Not Disturb (DND) settings, and notification categories.
Core Features
Multiple Delivery Channels
- Email: Default channel using Spring Mail
- SMS: Twilio integration for SMS delivery
- WhatsApp: WhatsApp Business API integration
- Telegram: Telegram Bot API integration
- Firebase Cloud Messaging (FCM): Push notifications for mobile devices
Notification Categories
- BILLING: Payment and subscription-related notifications
- SECURITY: Password changes, security alerts
- SUPPORT: Support ticket updates
- PROMOTIONAL: Marketing and special offers
- SYSTEM: System maintenance and updates
- ACCOUNT: Account-related changes
- SUBSCRIPTION: Subscription status updates
User Preferences Management
- Per-channel enable/disable settings
- Category-based filtering
- DND (Do Not Disturb) scheduling
- Timezone-aware delivery
- Localization support
System Architecture
graph TD
A[Client Application] --> B[GraphQL API Layer]
B --> C[MultiChannelNotificationService]
C --> D[Channel Services]
D --> E[EmailService]
D --> F[SmsService]
D --> G[WhatsAppService]
D --> H[TelegramService]
D --> I[FCMService]
J[NotificationPreferences] --> C
K[MessageTemplates] --> C
L[RateLimiter] --> C
GraphQL API Reference
Notification Preferences
Get User Preferences
query GetNotificationPreferences {
getNotificationPreferences {
enabledChannels
enabledCategories
dndEnabled
dndStartTime
dndEndTime
timezone
}
}
Update Preferences
mutation UpdateNotificationPreferences($input: NotificationPreferencesInput!) {
updateNotificationPreferences(input: $input) {
enabledChannels
enabledCategories
dndEnabled
dndStartTime
dndEndTime
timezone
}
}
input NotificationPreferencesInput {
enabledChannels: [NotificationChannel!]!
enabledCategories: [NotificationCategory!]!
dndEnabled: Boolean
dndStartTime: String
dndEndTime: String
timezone: String
}
Channel-Specific Operations
Send WhatsApp Notification
mutation SendWhatsAppNotification(
$userId: Int
$username: String
$message: String!
) {
sendWhatsAppNotification(
userId: $userId
username: $username
message: $message
)
}
Send Telegram Notification
mutation SendTelegramNotification(
$userId: Int
$username: String
$message: String!
) {
sendTelegramNotification(
userId: $userId
username: $username
message: $message
)
}
Send FCM Notification
mutation SendNotificationByToken(
$token: String!
$notification: NotificationInput!
) {
sendNotificationByToken(token: $token, notification: $notification) {
status
message
}
}
input NotificationInput {
subject: String!
content: String!
}
Administrative Operations
Get Notification Stats
query GetNotificationStats {
getNotificationStats {
totalNotificationsSent
notificationsByChannel {
channel
count
successRate
}
notificationsByCategory {
category
count
}
failedNotifications
}
}
Implementation Examples
Sending Multi-Channel Notification
// Using MultiChannelNotificationService
public void sendNotification(
User user,
String messageKey,
NotificationCategory category,
Map<String, Object> variables,
Function<NotificationMessage, String> messageProvider) {
NotificationPreferences prefs = getPreferences(user);
UserProfile profile = user.getProfile();
if (!prefs.isCategoryEnabled(category) || prefs.isDndActive()) {
log.debug("Notification skipped - Category disabled or DND active");
return;
}
for (NotificationChannel channel : prefs.getEnabledChannels()) {
try {
NotificationMessage message = new NotificationMessage(channel, variables);
String content = messageProvider.apply(message);
sendToChannel(channel, user, profile, content, messageKey, variables);
} catch (Exception e) {
log.error("Failed to send notification through channel {}", channel, e);
}
}
}
Channel-Specific Implementation
FCM Service
public FcmNotificationDto sendNotification(NotificationDto notificationDto, String token) {
Message message = Message.builder()
.setToken(token)
.setNotification(Notification.builder()
.setTitle(notificationDto.getSubject())
.setBody(notificationDto.getContent())
.build())
.putAllData(convertToStringData(notificationDto.getData()))
.setAndroidConfig(getAndroidConfig())
.setApnsConfig(getApnsConfig(notificationDto))
.build();
try {
String response = firebaseMessaging.sendAsync(message).get();
return new FcmNotificationDto();
} catch (Exception e) {
return new FcmNotificationDto("Failed to send FCM notification: " + e.getMessage());
}
}
Rate Limiting
The system implements rate limiting using token bucket algorithm:
public class MessageRateLimiter {
private final Map<String, Bucket> whatsappBuckets = new ConcurrentHashMap<>();
private final Map<String, Bucket> telegramBuckets = new ConcurrentHashMap<>();
public boolean tryConsumeWhatsApp(String phoneNumber) {
Bucket bucket = whatsappBuckets.computeIfAbsent(phoneNumber,
k -> createBucket(config.getWhatsapp()));
return bucket.tryConsume(1);
}
public boolean tryConsumeTelegram(String chatId) {
Bucket bucket = telegramBuckets.computeIfAbsent(chatId,
k -> createBucket(config.getTelegram()));
return bucket.tryConsume(1);
}
}
Error Handling
Common error scenarios and their handling:
Error Type | Description | Handling Strategy |
---|---|---|
Channel Unavailable | Communication channel is down | Retry with exponential backoff |
Rate Limited | Too many requests | Wait for rate limit reset |
Invalid Recipient | Invalid phone/email/token | Log error and skip delivery |
Template Error | Message template issues | Fall back to default template |
DND Violation | Message during DND period | Queue for later delivery |
Best Practices
-
Template Management
- Use language-specific message templates
- Support HTML and plain text formats
- Include fallback templates
- Validate template variables
-
Error Handling
- Implement retry mechanisms
- Log delivery failures
- Monitor error rates
- Provide fallback channels
-
Performance
- Use async operations
- Implement caching
- Batch similar notifications
- Queue non-urgent messages
-
Security
- Validate input data
- Rate limit per user/channel
- Encrypt sensitive data
- Audit notification delivery
Configuration
The system can be configured through application.yml:
messaging:
telegram:
bot-token: "your-bot-token"
bot-username: "your-bot-username"
admin-group-id: "admin-group-id"
whatsapp:
connection:
retry-attempts: 3
retry-delay: 5000
timeout: 30000
templates:
location: "classpath:templates/messages"
cache-ttl: 3600
tracking:
enabled: true
retention-days: 30
cleanup-interval: 86400
queue:
max-size: 10000
worker-threads: 5
batch-size: 100
process-interval: 60000
Monitoring and Statistics
Key metrics to monitor:
- Delivery success rate per channel
- Error rates and types
- Template rendering performance
- Queue sizes and processing times
- Rate limit utilization
- User preference patterns
Troubleshooting Guide
Common Issues
-
Messages Not Delivered
- Check channel status
- Verify recipient details
- Check rate limits
- Review DND settings
-
Template Issues
- Validate template syntax
- Check variable mapping
- Verify locale settings
- Review template cache
-
Performance Problems
- Monitor queue size
- Check worker thread status
- Review batch processing
- Analyze rate limiting impact
Future Enhancements
Planned improvements:
-
Additional Channels
- Slack integration
- Discord support
- Microsoft Teams connection
- Web push notifications
-
Enhanced Features
- Message scheduling
- Rich media support
- Interactive templates
- Advanced analytics
-
Performance Optimizations
- Improved caching
- Better batching
- Smarter rate limiting
- Enhanced monitoring