Отложенные задачи: напоминание через 24 часа
Вопрос
Нужно отправить пользователю напоминание через 24 часа после регистрации, если он не подтвердил email. Сервис в нескольких репликах. Как сделаете?
Попробуйте сами
Ответьте вслух за 2 минуты, как на собесе. Потом сверьтесь с тезисами: что прозвучало, а что нет.
Показать ответ и разбор
Коротко
Что должно прозвучать в ответе
Не `setTimeout`: таймер в памяти теряется при рестарте и дублируется в репликах
Вариант 1: отложенная задача в очереди (BullMQ `delay`, отложенные сообщения брокера) с jobId от userId для дедупликации
Вариант 2: запись в таблицу с `run_at` и воркер, который выбирает созревшие задачи через `SELECT ... FOR UPDATE SKIP LOCKED`
В момент выполнения перепроверяю условие (email всё ещё не подтверждён), потому что за сутки состояние могло измениться
Идемпотентность и ретраи: повтор задачи не шлёт второе письмо (отметка об отправке)
Мониторинг: отставание очереди, упавшие задачи, DLQ
Что могут спросить следом
- Почему перепроверять условие в момент выполнения?
- Как отменить задачу, если пользователь подтвердил email?
- Что будет при миллионе задач на одну секунду?
Разбор
Таймер в процессе не подходит: при рестарте он теряется, а в четырёх репликах сработает четыре раза. Нужно надёжное хранилище задач. Если в проекте есть Redis, беру BullMQ с delay и jobId, построенным из userId: повторная постановка не создаст дубль, а задачу можно удалить при подтверждении email. Если хочется без лишней инфраструктуры, таблица jobs(run_at, payload, status) и воркер, который раз в несколько секунд забирает созревшие задачи через FOR UPDATE SKIP LOCKED: реплики не мешают друг другу и не берут одно и то же. В момент выполнения обязательно перепроверяю условие, потому что за сутки пользователь мог подтвердить почту. Обработчик идемпотентный, с отметкой об отправке, чтобы ретрай не прислал второе письмо. И мониторю отставание очереди и упавшие задачи.
Ответьте сами, а не прочитайте
В тренажёре вопрос попадёт в повторения и вернётся, когда начнёт забываться. Плюс билеты с зачётом: 20 вопросов, не больше 2 ошибок.