Система следует событийно-ориентированной микросервисной архитектуре, где уведомления проходят через центральный конвейер перед отправкой в любой канал доставки.
Клиент отправляет запрос на уведомление в API Gateway, который пересылает его в Notification Service. Этот сервис обрабатывает валидацию, обогащение данных и логику маршрутизации перед отправкой сообщений в Message Queue (например, Kafka или RabbitMQ).
Каждый канал имеет выделенный воркер-консьюмер, который читает из очереди:
PushWorker — обрабатывает мобильные push-уведомления через FCM/APNsEmailWorker — отправляет через SendGrid или SESSMSWorker — доставляет через TwilioInAppWorker — записывает в real-time хранилище (например, Redis или WebSocket layer)Такой дизайн делает добавление новых каналов таким простым, как деплой нового воркера без изменения существующего кода — это воплощение принципа открытости/закрытости.
Preference Service хранит настройки каналов для каждого пользователя и часы тишины. Перед добавлением в очередь система проверяет эти предпочтения и применяет rate limiting с помощью алгоритма token bucket или sliding window (хранится в Redis), чтобы предотвратить спам уведомлений.
Ошибки доставки повторяются с использованием exponential backoff с настраиваемым максимальным количеством попыток. После исчерпания всех повторов сообщения перемещаются в Dead Letter Queue (DLQ) для ручной проверки или оповещения.
Template Service управляет версионированными, локализуемыми шаблонами сообщений с подстановкой переменных. Запланированные уведомления хранятся с временной меткой deliver_at и запускаются Scheduler Service (например, с помощью cron jobs или Quartz).
Каждое событие доставки — отправлено, доставлено, открыто, кликнуто — публикуется в Analytics Pipeline (например, Kafka → ClickHouse) для real-time дашбордов и отчётов по open rate и click rate.
Массовые уведомления (например, маркетинговые кампании) разбиваются на батчи настраиваемого размера и добавляются в очередь постепенно, чтобы избежать перегрузки очереди.
Система использует выделенных consumer workers для каждого канала доставки, что позволяет добавлять новые каналы, просто развернув новый worker без модификации существующего кода, демонстрируя соответствие принципу Open/Closed Principle.
Новый — ещё не проверен сообществом
Вы