Skip to content

Репозиторий для сервиса нотификаций

Notifications You must be signed in to change notification settings

Rusich90/notifications_sprint_1

Repository files navigation

#Первый запуск

Команда для первого запуска приложения (поднимет докер-композ, создаст базу и загрузит в нее дамп с тестовыми юзерами)

make first-up

Эндпоинт для фейковой регистрации в кинотеатре:

http://localhost:8000/api/fake/registration

Welcome письмо можно найти в инбоксе мэилхога:

http://localhost:8025/

Для остановки и удаления контейнеров

docker-compose down

Для следующих запусков

docker-compose up

Проектная работа 10 спринта

Проектные работы в этом модуле в команде. Задания на спринт вы найдёте внутри тем.

Задание на модуль

  • Спроектируйте сервис email-рассылок с учётом потенциального расширения количества способов связи.
  • Настройте отправку одинаковых писем всем пользователям.
  • Настройте отправку персонифицированных писем.
  • Отправляйте приветственное письмо после регистрации пользователя.

Задание

Спроектируйте ваш сервис уведомлений и отправьте наставнику на проверку. Повторим, какие возможные компоненты есть в системе нотификации:

  1. База, в которой хранятся уведомления notification_id и content_id.
  2. API для приёма событий по созданию уведомлений (а может стоит через него управлять и уведомлениями в базе?):
  • API процесс;
  • база, в которой хранится история отправки уведомлений (а может и не здесь).
  1. Процесс, который отправляет уведомление (воркер):
  • База, в которой хранится история отправки уведомлений (а может и не здесь).
  1. Генератор автоматических событий:
  • шедулер;
  • cron;
  • база, в которой хранится периодичность уведомлений (а лучше бы это была одна база с п. 1).
  1. Админ-панель.

Задание 1

В уроке рассматривались два варианта подготовки данных для отправки уведомлений: собирать данные до воркера и отправлять их в него или собирать данные в самом воркере.

Лучше всего использовать третий вариант — гибридный.

Спроектируйте и распишите гибридный формат работы API, воркера, генератора автоматических уведомлений и админ-панели для трёх сценариев:

  1. Любая часть сайта просит отправить мгновенное уведомление.
  2. Генератор автоматических событий сгенерировал событие или события на большую группу пользователей.
  3. Админ-панель, в которой менеджеры вручную создали рассылку уведомлений пользователям.

Задание 2

Спроектируйте сервис уведомлений. Используйте готовые компоненты и подходы из урока, инструменты из прошлого модуля, а главное — свои идеи и решения конкретных сценариев.

Требования к итоговой архитектуре:

  • Для простоты можно рассылать только email-письма, но система должна иметь возможность расширения на другие типы уведомлений: смс, push и другие варианты.
  • Мгновенные уведомления должны отправляться с максимальной задержкой в несколько минут.
  • В случае падения любого компонента ничего не должно потеряться и любое уведомление должно быть получено клиентом.
  • В случае простоя генератора автоматических уведомлений (или аналогичного компонента) после его запуска не должны дублироваться старые и новые события.
  • Должна быть возможность настройки уведомлений пользователем, в том числе отключение уведомлений.
  • Должна быть единая система шаблонизации email-писем как для автоматических уведомлений, так и для рассылок, созданных менеджером .
  • У системы должна быть возможность масштабироваться.

Задания

Задание 1

Для лаконичности код сервера написан без учёта внештатных ситуаций. Предполагается, что каждый пользователь верно вводит команды и никогда не опечатывается. Также в нём опущена обработка отключений от сервера. Если Хитрый лис покинет чат, он всё ещё останется в списке присутсвующих. Доработайте программу, чтобы она реагировала предупреждением на сообщения непредусмотренного формата, а при закрытии пользователем соединения, убирала его из списка peoples.

Задание 2

Напишите python-клиента, который подключится к ws-серверу и будет 10 раз в секунду отправлять всем получателям хулиганское сообщение.

import asyncio
import websockets

uri = "ws://localhost:8765"

async def spammer():
    # Используйте менеджер контекста, чтобы соединение автоматически закрылось при выходе из блока
    async with websockets.connect(uri) as websocket:
        pass # Здесь вам пригодятся websocket.send, websocket.recv и asyncio.sleep

loop = asyncio.get_event_loop()
loop.run_until_complete(spammer()) 

Бонусное задание

Победите своего бота: добавьте серверу защиту от слишком частых повторений сообщений и добавьте пользователям возможность заблокировать нежелательный контакт.

Задание

  • Реализуйте в своём сервисе модуль, отвечающий за генерацию и отправку персонализированных писем.
  • Реализуйте модуль для работы с Websoket.

Задача

Отдел маркетинга запускает новую рекламную кампанию. Нужно привлечь внимание пользователей к новым фичам онлайн-кинотеатра и увеличить конверсию в покупку новых фильмов. Для этого каждому пользователю необходимо отправить письмо с информацией и данными.

Технически требуется загрузить все письма в очередь на рассылку и полностью обработать её.

Пропишем чек-лист, чтобы ничего не забыть:

  • Персонифицировать каждое письмо. Для этого создайте шаблон письма с подставляемыми данными, который будет обогащаться данными пользователя перед отправкой.
  • При обогащении данными предусмотреть возможное влияние пиковой нагрузки на распределённую систему. Одновременная обработка большого количества данных не должна приводить, например, к отказу подсистемы данных о пользователях при большом количестве одновременных запросов за данными.
    • Подсказка: регулировать нагрузку можно количеством одновременных запущенных консьюмеров. Также можно управлять скоростью работы каждого отдельного консьюмера при помощи таймаутов (sleep).
    • Ещё подсказка: снизить аффект на распределённую систему можно выделением специализированных slave-нод с данными только под чтение операции. Master-сервер при этом продолжит обслуживать клиентов в штатном режиме. Этот способ поможет распределить нагрузку, однако он дороже, сложнее в реализации и имеет свои особенности. Например, отставание slave-ноды от master: так вы рискуете отправить устаревшие данные.
  • Предусмотреть failover-стратегию. Одна из подсистем всё-таки отказала. Что будет происходить с запущенной рассылкой? Как восстановить упавшую подсистему? Как снизить нагрузку на подсистему сразу после её восстановления?
    • Подсказка: при отказе одной из подсистем нужно иметь возможность мгновенно отключить любые запросы на неё. Это можно сделать, например, остановив все консьюмеры подготовки или отправки писем. После восстановления нужно отрегулировать входящую нагрузку на подсистему, чтобы не получилось повторного отказа. Опять же это можно сделать регулировкой количества одновременно запущенных консьюмеров и скоростью работы каждого консьюмера.
  • При загрузке большого количества писем в очередь предусмотреть возможность снижения пикового RPS на запись. Это нужно для снижения аффекта на другие очереди этого сервера.
    • Подсказка: в процессе считывания данных из БД и публикации сообщений в очередь RabbitMQ на обработку, предусмотрите возможность искусственного занижения скорости публикации. Это можно сделать, встроив в цикл операцию sleep. Если пиковый RPS на запись начнёт аффектить другие очереди на том же сервере, нужно понизить скорость отправки сообщений в шину, увеличив параметр sleep.
  • Предусмотреть в консьюмерах обработку ситуации с временными ошибками внешних сервисов. Они не должны приводить к потере конкретного сообщения.
    • Подсказка: иногда при потоковой обработке большого объёма данных могут «выстреливать» временные ошибки, например, флап базы данных или сети. В таких ситуациях обычно консьюмеры начинают ределиверить — пытаться снова и снова обработать сообщение и тем самым останавливают обработку всей очереди. Для таких ситуаций научите консьюмеров деградировать — отправлять проблемное сообщение во временную очередь, чтобы через некоторое время вернуться к его обработке. В RabbitMQ это делается через Dead Letter Queue.
  • Убедиться, что обработка каждого сообщения идемпотентна. То есть повторная обработка того же самого сообщения не приводит к повторной отправке письма.

Задача

Реализуйте рассылку welcome-писем пользователям после регистрации в онлайн-кинотеатре. Welcome-письмо обычно содержит приветственное сообщение и инструкции, как подтвердить email, указанный при регистрации.

Что нужно сделать:

  • После регистрации пользователя в сервисе онлайн-кинотеатра отправлять приветственное письмо на указанный пользователем адрес электронной почты.
  • В письме должна быть ссылка для подтверждения адреса электронной почты.
  • Для удобной работы на мобильных устройствах сделайте ссылку в письме сокращённой.
  • Сокращённая ссылка должна включать:
    • уникальный идентификатор пользователя, чтобы считать визиты,
    • временну́ю метку, обозначающую период, до которого ссылка действительна,
    • параметр redirectUrl, определяющий, куда перенаправить пользователя после успешного подтверждения адреса электронной почты.
  • При переходе по просроченной ссылке должна открываться страница с ошибкой 404.
  • При переходе по действительной ссылке в базе должен проставляться признак, что этот email подтверждён.
  • После успешного подтверждения адреса электронной почты система перенаправляет пользователя по адресу redirectUrl.
  • Конкретное значение параметра redirectUrl настраивается в панели админа. В ходе выполнения этого задания настройте редирект на главную страницу онлайн-кинотеатра.

About

Репозиторий для сервиса нотификаций

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages