Functional Scope (In-Scope)
- Multi-Channel Dynamic Routing: Route notifications dynamically via SMS, Email, and Push based on cost or speed strategies.
- Highly Granular Priority Blocking queues: Implement urgent, high, and normal priority levels inside active queues.
- Pluggable Message Enrichment (Decorator Pattern): Enrich notifications dynamically with features like tracking tokens, base64 encryption, or metadata signatures without changing the core structures.
- Gateway Rate Limiting: Refill and throttle outbound dispatching to match target SMS/Email API rate capacities.
- Deduplication Filtering: Safe idempotency check to avoid repeat deliveries of the same messages.
Explicit Boundaries (Out-of-Scope)
- No Real Network Mail Transport Socket: Bypasses raw SMTP, Twilio API integrations, or APNS configurations.
- No Dynamic Content Layout Templates: All template processing, localization, and rich formats reside out-of-scope.
Thread-safe priority messaging blueprints in Java and Python:
// ─── JAVA BLUEPRINT ──────────────────────────────────────────────────────────
import java.util.*;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;
enum ChannelType { SMS, EMAIL, PUSH }
enum Priority {
URGENT(0), HIGH(1), NORMAL(2);
private final int value;
Priority(int val) { this.value = val; }
public int getValue() { return value; }
}
interface SendableNotification {
String getId();
String getRecipient();
String getContent();
ChannelType getChannel();
Priority getPriority();
}
class SimpleNotification implements SendableNotification {
private final String id;
private final String recipient;
private final String content;
private final ChannelType channel;
private final Priority priority;
public SimpleNotification(String id, String recipient, String content, ChannelType channel, Priority priority) {
this.id = id;
this.recipient = recipient;
this.content = content;
this.channel = channel;
this.priority = priority;
}
public String getId() { return id; }
public String getRecipient() { return recipient; }
public String getContent() { return content; }
public ChannelType getChannel() { return channel; }
public Priority getPriority() { return priority; }
}
// ─── DECORATOR PATTERN (ENRICHMENT) ──────────────────────────────────────────
abstract class NotificationDecorator implements SendableNotification {
protected final SendableNotification decorated;
public NotificationDecorator(SendableNotification decorated) { this.decorated = decorated; }
public String getId() { return decorated.getId(); }
public String getRecipient() { return decorated.getRecipient(); }
public String getContent() { return decorated.getContent(); }
public ChannelType getChannel() { return decorated.getChannel(); }
public Priority getPriority() { return decorated.getPriority(); }
}
class EncryptedNotificationDecorator extends NotificationDecorator {
public EncryptedNotificationDecorator(SendableNotification decorated) { super(decorated); }
@Override
public String getContent() {
return "[ENCRYPTED] " + Base64.getEncoder().encodeToString(decorated.getContent().getBytes());
}
}
class TrackingNotificationDecorator extends NotificationDecorator {
private final String trackerId;
public TrackingNotificationDecorator(SendableNotification decorated, String trackerId) {
super(decorated);
this.trackerId = trackerId;
}
@Override
public String getContent() {
return decorated.getContent() + " [TrackingRef: " + trackerId + "]";
}
}
// ─── STRATEGY PATTERN (DYNAMIC ROUTING) ──────────────────────────────────────
interface RoutingStrategy {
ChannelType route(SendableNotification notification);
}
class CostEffectiveRouting implements RoutingStrategy {
@Override
public ChannelType route(SendableNotification n) {
if (n.getPriority() == Priority.URGENT) return ChannelType.SMS;
return ChannelType.EMAIL;
}
}
class PushPreferredRouting implements RoutingStrategy {
@Override
public ChannelType route(SendableNotification n) {
return ChannelType.PUSH;
}
}
// ─── RATE LIMITER (TOKEN BUCKET) ──────────────────────────────────────────────
class TokenBucketRateLimiter {
private final int capacity;
private final long refillRateMs;
private int tokens;
private long lastRefillTime;
public TokenBucketRateLimiter(int capacity, long refillRateMs) {
this.capacity = capacity;
this.refillRateMs = refillRateMs;
this.tokens = capacity;
this.lastRefillTime = System.currentTimeMillis();
}
public synchronized boolean tryAcquire() {
refill();
if (tokens > 0) {
tokens--;
return true;
}
return false;
}
private void refill() {
long now = System.currentTimeMillis();
long elapsed = now - lastRefillTime;
if (elapsed >= refillRateMs) {
int newTokens = (int) (elapsed / refillRateMs);
tokens = Math.min(capacity, tokens + newTokens);
lastRefillTime = now;
}
}
}
// ─── FACTORY METHOD FOR CHANNELS ─────────────────────────────────────────────
interface NotificationChannel {
boolean send(SendableNotification notification);
}
class SMSChannel implements NotificationChannel {
public boolean send(SendableNotification n) {
System.out.println("[SMS Gateway] Sending to " + n.getRecipient() + ": " + n.getContent());
return true;
}
}
class EmailChannel implements NotificationChannel {
public boolean send(SendableNotification n) {
System.out.println("[Email Gateway] Sending to " + n.getRecipient() + ": " + n.getContent());
return true;
}
}
class PushChannel implements NotificationChannel {
public boolean send(SendableNotification n) {
System.out.println("[Push Gateway] Sending to " + n.getRecipient() + ": " + n.getContent());
return true;
}
}
class ChannelFactory {
private static final Map<ChannelType, NotificationChannel> channels = new ConcurrentHashMap<>();
static {
channels.put(ChannelType.SMS, new SMSChannel());
channels.put(ChannelType.EMAIL, new EmailChannel());
channels.put(ChannelType.PUSH, new PushChannel());
}
public static NotificationChannel getChannel(ChannelType type) {
return channels.get(type);
}
}
// ─── CONCURRENT NOTIFICATION SERVICE ──────────────────────────────────────────
class NotificationService {
private final PriorityBlockingQueue<SendableNotification> queue = new PriorityBlockingQueue<>(100,
Comparator.comparingInt(n -> n.getPriority().getValue()));
private final Set<String> idempotencyStore = ConcurrentHashMap.newKeySet();
private final List<SendableNotification> deadLetterQueue = new CopyOnWriteArrayList<>();
private final TokenBucketRateLimiter rateLimiter = new TokenBucketRateLimiter(5, 500); // 5 per 500ms
private final RoutingStrategy routingStrategy;
private final ExecutorService executor = Executors.newFixedThreadPool(2);
private volatile boolean running = true;
public NotificationService(RoutingStrategy routingStrategy) {
this.routingStrategy = routingStrategy;
for (int i = 0; i < 2; i++) {
executor.submit(this::processQueue);
}
}
public boolean submitNotification(SendableNotification n) {
if (!idempotencyStore.add(n.getId())) {
System.out.println("[Service] Discarding duplicate notification ID: " + n.getId());
return false;
}
queue.offer(n);
return true;
}
private void processQueue() {
while (running) {
try {
SendableNotification n = queue.poll(100, TimeUnit.MILLISECONDS);
if (n == null) continue;
if (!rateLimiter.tryAcquire()) {
System.out.println("[Service] Rate limit hit! Re-queueing notification: " + n.getId());
queue.offer(n);
Thread.sleep(100);
continue;
}
ChannelType targeted = routingStrategy.route(n);
NotificationChannel channel = ChannelFactory.getChannel(targeted);
boolean success = channel.send(n);
if (!success) {
System.out.println("[Service] Delivery failed for: " + n.getId() + ". Sending to DLQ.");
deadLetterQueue.add(n);
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
break;
}
}
}
public void shutdown() {
running = false;
executor.shutdown();
}
}
public class Main {
public static void main(String[] args) throws InterruptedException {
System.out.println("=== Notification Service Concurrent Driver ===");
NotificationService service = new NotificationService(new CostEffectiveRouting());
SendableNotification n1 = new SimpleNotification("MSG-001", "+15550199", "Your OTP is 4829", ChannelType.SMS, Priority.URGENT);
SendableNotification n2 = new SimpleNotification("MSG-002", "alice@example.com", "Welcome onboard!", ChannelType.EMAIL, Priority.NORMAL);
// Wrap with Decorators
SendableNotification enriched = new TrackingNotificationDecorator(
new EncryptedNotificationDecorator(n2), "TRACK-999"
);
service.submitNotification(n1);
service.submitNotification(enriched);
service.submitNotification(n1); // Duplicate check
Thread.sleep(1000);
service.shutdown();
}
}