【问题标题】:Rails 4: How to send mail in a separate thread?Rails 4:如何在单独的线程中发送邮件?
【发布时间】:2015-07-06 17:51:57
【问题描述】:

我有一个应用程序,当管理员做某事时,它需要偶尔向整个用户群发送电子邮件。这工作正常,但是当有很多用户时,管理员页面将等到所有邮件都发送完毕,这是不可取的。

为了缓解这种情况,我尝试在新线程中发送电子邮件:

t = Thread.new do
  User.all.each do |user|
    Mailer.email(user).deliver
  end
end
at_exit{ t.join }

这很好,但是在我的测试套件中,我无法测试以确保电子邮件发送正常:

# This test now fails with the new Thread above
test "admin action should send email blast" do
  assert_difference("ActionMailer::Base.deliveries.count", User.count) do
    post :action
  end
end

所以我的问题是:

  1. 这种方法是在新线程中发送电子邮件的最佳方式吗?或者是否有可用的 gem 来处理这种交互?
  2. 如果发送是在新线程中完成的,我如何测试电子邮件是否在我的测试套件中发送?有没有办法检查等待所有线程完成?

【问题讨论】:

  • 1. 我只是将发送电子邮件逻辑提取到一个单独的方法中,然后对其进行测试。 2. 有一种方法可以通过调用 Thread.join 方法或在您的情况下为 t.join 进行检查之前等待所有线程完成

标签: ruby-on-rails multithreading email ruby-on-rails-4


【解决方案1】:

在单独的线程中发送电子邮件的最佳方式是使用延迟作业或类似的 gem。

https://github.com/collectiveidea/delayed_job

使用延迟作业 gem,您还可以在预定时间在不同线程中发送电子邮件或执行其他操作。

另一个选择是使用sidekiq,安装sidekiq gem并将这一行添加到application.rb文件中

config.active_job.queue_adapter = :sidekiq

【讨论】:

    【解决方案2】:

    我更喜欢对异步任务使用基于队列的方法。 [延迟工作] (https://github.com/collectiveidea/delayed_job) 是一种选择,但我更喜欢使用 [sidekiq] (http://sidekiq.org)。

    [这里] (http://blog.remarkablelabs.com/2013/01/using-sidekiq-to-send-emails-asynchronously) 是使用 sidekiq 异步发送电子邮件的示例。

    【讨论】:

      【解决方案3】:

      在 Rails 4.2 中有一个特殊的类处理称为 ActiveJob 的作业,活动作业允许您将长任务排队等待另一个进程在后台处理它们,您也可以将任务排队一段时间,例如“明天早上 8 点发送这封电子邮件”。

      要处理这些队列,您需要选择一个后端来处理它们,这里是list of backends that support ActiveJob

      各有优缺点,例如 sidekiq 是一个多线程处理程序,因此它使用较少的内存,而例如,sucker punch 使用与主服务器相同的线程,因此它使用的内存要少得多,如果您有无法处理第二个 ruby​​ 线程的低内存服务器。

      至于测试部分,rails guide 已经解释了如何测试您的电子邮件并测试诸如电子邮件是否已排队、测试是否呈现了正确的模板以及它是否包含正确的文本。

      【讨论】:

        【解决方案4】:

        我认为您想异步发送邮件,为此您可能会使用许多 gem,例如延迟作业、sidekiq 等。我个人建议使用 sidekiq 更快,并在后台使用内存数据库中的 Redis。

        在 Rails 4.2 中,引入了主动作业,因此使用它的优点是您可以随时从一个排队系统切换到另一个排队系统而无需担心,并且您可以指定您想要的排队机器

        module YourApp
         class Application < Rails::Application
          # Be sure to have the adapter's gem in your Gemfile
          # and follow the adapter's specific installation
          # and deployment instructions.
          config.active_job.queue_adapter = :sidekiq
         end
        end
        

        【讨论】:

          猜你喜欢
          • 2011-09-30
          • 1970-01-01
          • 1970-01-01
          • 2014-01-13
          • 1970-01-01
          • 2013-03-11
          • 1970-01-01
          • 1970-01-01
          • 2022-11-30
          相关资源
          最近更新 更多