Как правильно реализовать систему очередей для асинхронного подтверждения авторизации, путем ожидания кода
Имеется puppeteer сервер который выполняет авторизацию на сервере, он служит в качестве удобной авторизации над сервисом, предлагая возможность в качестве мультиаккаунтности. Проще говоря, свой сервис, который дополняет другой сервис, который этого сделать не может.
Существует разовая авторизация с подтверждением по СМС коду, код вводится вручную, затем аккаунт добавляется в базу и в дальнейшем допускается возможность заходить из под разных устройств в одном месте.
В чем заключается проблема:
При заполнении первичных данных, для входа требуется подтверждение, по смс, первичный вход заключается в подстановке данных пользователя на сервис, это выполняется асинхронно и необходимо дождаться смс подтверждения для входа.
Данную систему я организовал через брокер сообщений RabbitMQ. В брокер поступают сообщения, а дальше эти сообщения идут на сервер, там они выполняются.
Система авторизации в брокере разбита на две части.
Получение первичных данных (логин / пароль).
Подтверждение входа через СМС код.
Я сделал две очереди которые независимо друг от друга получают данные и код, поэтому они разбиты.
Как организовать систему так, чтобы после ввода данных и обработки их, сервер ждал код?
Для себя я вижу два варианта решения задачи:
Внутри слушателя данных сделать еще один слушатель, который будет ждать код и проверять на соответствие, относится ли он к текущим данным (т.к. кодов может быть много и они будут доставляться к разным пользователям в разное время).
Создать слушатель на одном уровне с авторизацией и завести переменную, в которую буду помещать все пришедшие коды и удалять их из переменной по истечению времени. Данную переменную я буду смотреть через Proxy и если находить соответствия выполнять свои действия дальше.
Какой из этих вариантов более правильный?
Какой вообще есть вариант выхода из данной ситуации?
Я просто хотел ждать код для своей очереди чтобы применить действие, но сделать это непосредственно в ней или же один раз за ее пределами, вот в чем заключается вопрос.
Ответы (1 шт):
Вы пытаетесь использовать очереди сообщений в режиме Запрос-Ответ, такого режима следует избегать. Использование этого шаблона зачастую и приводит к решению проблем, которых не должно возникать (создание потребителя внутри потребителя) или излишнему усложнению системы, когда приходится создавать Саги, чтобы корректно отработать многоступенчатый процесс. Вместо запрос-ответ гораздо лучше использовать событийную архитектуру, когда вместо категорий запросов вы начинаете мыслить категориями событий. В случае описанного вами процесса, событийную архитектуру можно описать следующим образом:
- Пользователь ввёл логин-пароль в сервисе А - в очередь отправляется событие ICredentialsReceived.
- Сервис-подписчик Б получает событие и выполняет потребление - проверяет логин-пароль, сохраняет и отправляет временный СМС-код и публикует событие ISmsCodeSent.
- Сервис-подписчик А получает событие и переключает пользователя на страницу ввода СМС-кода.
- После ввода СМС-кода, сервис А отправляет событие ISmsCodeSubmit с введённым кодом.
- Сервис-подписчик Б получает событие, сверяет СМС-код с сохранённым и если всё правильно, то отправляет событие ILoginSucceeded.
- Сервис-подписчик А получает событие и пропускает пользователя в систему.
Как видите, в событийной парадигме вам не приходится сталкиваться с описанными вами сложностями. Но у всего есть своя цена - в таком режиме обычно происходит небольшое усложнение процесса коммуникации (больше фаз, событий, обработчиков).