Разница между Job Job/Mailer `deliver_now` и` deliver_later`
Общим шаблоном для взаимодействия с ActionJob
в Rails является настройка задания с помощью метода perform()
, который вызывается асинхронно через perform_now
или perform_later
В специальном случае Mailers вы можете напрямую вызвать deliver_now
или deliver_later
, так как ActionJob
хорошо интегрирован с ActionMailer
.
Документация rails содержит следующие комментарии -
# If you want to send the email now use #deliver_now
UserMailer.welcome(@user).deliver_now
# If you want to send the email through Active Job use #deliver_later
UserMailer.welcome(@user).deliver_later
В формулировке кажется, что deliver_now
не будет использовать ActiveJob
для отправки почты. Это правильно, и если да, то какова истинная разница между deliver_now
и deliver_later
? Не является ли асинхронным?
Аналогично, то же самое относится к perform_now
и perform_later
?
Спасибо!
Ответы
Ответ 1
Как вы говорите в своем вопросе, deliver_now
не использует ActiveJob
.
В принципе, deliver_later
является асинхронным. Когда вы используете этот метод, письмо не отправляется на данный момент, а скорее переносится в очередь заданий. Если задание не запущено, письмо не будет отправлено. deliver_now
отправит электронное письмо на данный момент, независимо от того, каково состояние работы. Здесь вы можете увидеть документацию для методов deliver
.
В соответствии с вашим вторым вопросом perform_now
будет обрабатывать задание немедленно, не отправляя в очередь. perform_later
, однако, добавит задание в очередь, и как только очередь заданий будет бесплатной, будет выполняться задание. Здесь вы можете увидеть документацию для методов perform
.
Ответ 2
В дополнение к тому, что написал Даниель Баталла, вот еще одно замечание, которое я сделал: deliver_later
, кажется, выполняет ленивую оценку, а deliver_now
- нет.
У меня есть модель ActiveRecord с дополнительным атрибутом reset_token
, который не хранится в базе данных (это от Michael Hartl railstutorial.org, модель хранит хешированную версию токена в столбце reset_digest
).
При выполнении deliver_now
доступ к атрибуту @model
reset_token
в представлении почтовой программы дает токен reset, как и ожидалось. Однако при выполнении deliver_later
, @model.reset_token
всегда nil
. Кажется, что deliver_later
обновляет модель данными базы данных, а поскольку reset_token
является дополнительным атрибутом, который не поддерживается базой данных, он будет nil
в этой точке. (Документация кода слишком глубоко вложена для меня, чтобы проверить это в источнике.)
Майкл использует deliver_now
в учебнике. Я не знаю, что он делает это, чтобы избежать ленивой оценки. Но мне потребовалось некоторое время, чтобы понять, что мне просто нужно было изменить deliver_later
на deliver_now
, чтобы мои тесты проходили.