Rails - 使用delayed_job异步发送所有电子邮件

3

我正在使用delayed_job,并且非常满意(尤其是workless扩展程序)。

但我希望将我的应用程序中所有的邮件都设置为异步发送。

事实上,对于邮件程序提供的解决方案

# without delayed_job
Notifier.signup(@user).deliver

# with delayed_job
Notifier.delay.signup(@user)

不适合我,因为:

  • 不易维护
  • 从宝石中发送的邮件不是异步发送(devise, mailboxer

我可以使用这种扩展 https://github.com/mhfs/devise-async 但我更愿意一次性找出整个应用程序的解决方案。

我能否扩展 ActionMailer 来重写 .deliver 方法(像这里 https://dev59.com/71DTa4cB1Zd3GeqPKIsP#4316543,但它已过时了,几乎所有我在该主题上找到的文档都是4年前的)?

我正在使用 Ruby 1.9 和 Rails 3.2 与 activerecord。

感谢您的支持


你试过自己的建议吗?不过你得覆盖 Mail::Message 对象。 - DiegoSalazar
2个回答

0
一个简单的解决方案是在 Notifier 对象上编写一个实用方法,如下所示:
class Notifier

  def self.deliver(message_type, *args)
    self.delay.send(message_type, *args)
  end

end

发送注册电子邮件如下:
Notifier.deliver(:signup, @user)

这个实用方法提供了一个单一的点,如果需要的话,您可以将延迟作业替换为Resque或Sidekiq解决方案。


我喜欢这种方式。接近我最终所做的,尽管我没有在这里更新,因为它并没有完全回答“如何默认异步转换整个邮件程序”的问题。 - Augustin Riedinger

0

如果您已经完成了ActiveJob和并发库的设置这里有文档。最简单的解决方案是覆盖涉及交易邮件的设备send_devise_notification实例方法,如此处所示这里

class User < ApplicationRecord
  # whatever association you have here
  devise :database_authenticatable, :confirmable
  after_commit :send_pending_devise_notifications
  # whatever methods you have here

 protected
  def send_devise_notification(notification, *args)
    if new_record? || changed?
      pending_devise_notifications << [notification, args]
    else
      render_and_send_devise_message(notification, *args)
    end
  end

  private

  def send_pending_devise_notifications
    pending_devise_notifications.each do |notification, args|
      render_and_send_devise_message(notification, *args)
    end

    pending_devise_notifications.clear
  end

  def pending_devise_notifications
    @pending_devise_notifications ||= []
  end

  def render_and_send_devise_message(notification, *args)
    message = devise_mailer.send(notification, self, *args)

    # Deliver later with Active Job's `deliver_later`
    if message.respond_to?(:deliver_later)
      message.deliver_later
    # Remove once we move to Rails 4.2+ only, as `deliver` is deprecated.
    elsif message.respond_to?(:deliver_now)
      message.deliver_now
    else
      message.deliver
    end
  end

end

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接