deliver_later在rails任务中不能正常工作

时间:2017-10-19 14:59:29

标签: ruby-on-rails task actionmailer rails-activejob

我正在使用任务来完成后台工作。例如我在lib / tasks中的remove_badges.rake文件:

desc "Remove expired badges rake task"
task :remove_expired_badges => :environment do

  message = "remove_expired_badges is running now."
  HostMailer.send_system_info_mail(message).deliver_later

  BadgeHost.all.each do |b|
    if b.expire_at < Time.now
      begin
        b.destroy
        puts "An expired badge successfully deleted."

        host = b.host
        badge = b.badge
        HostMailer.send_badge_removed_email(host, badge).deliver_later

      rescue
        puts "Failed to destroy expired badge."
      end
    end
  end
end

首先发送邮件是为了确保此任务正在运行。 第二封邮件是用户通知他丢失了他的徽章。

我还有其他任务,其中一封邮件工作正常。

但在其他任务中,不会发送邮件。只有当我删除deliver_later并使用传递时,才会发送邮件。

我不想使用传递,因为它会在发送邮件之前暂停。

您是否知道导致deliver_later无法正常使用rails任务?

1 个答案:

答案 0 :(得分:1)

我正在处理发送电子邮件的Rails 5.0.1应用程序中的rake任务。我使用的是ActiveJob的异步适配器的默认设置(开发模式)。我还在开发中使用了letter_opener gem,以便在我的浏览器中弹出电子邮件而不是发送。

当我使用.deliver_now运行每个电子邮件的任务时,一切都很好。

为了让任务快速完成,我切换了rake任务,以便它生成的每封电子邮件都使用.deliver_later而不是.deliver_now排队。

我可以看到电子邮件被ActiveJob排队了:

[ActiveJob]排队的ActionMailer :: DeliveryJob ......

但是在开信刀中没有弹出电子邮件。

事实证明,问题在于我并不了解:异步如何工作。基本上,正在发生的事情是:async是一个内存队列,只有创建它的进程才会存在。使用rake任务,电子邮件会正确排队(在内存中),但随后任务结束并清除内存队列。但这是在为ActiveJob线程提供任何处理时间之前发生的。

要测试事情是否正在开发中,以下任何一项都可以使用:

Use .deliver_now
Add a sleep(5) to the end of your rake task (just for manual testing ... delete that before you commit)
Switch to a different ActiveJob adapter that stores the jobs in some durable queue / db and runs as a separate process from your rake task

答案:http://stevechanin.blogspot.com/2017/05/deliverlater-not-working-in-rake-tasks.html