使用延迟作业发送电子邮件时报告错误

Posted

技术标签:

【中文标题】使用延迟作业发送电子邮件时报告错误【英文标题】:Error reporting when sending emails with delayed_job 【发布时间】:2012-07-30 18:28:05 【问题描述】:

使用 AirBrake 或 ExceptionNotifier 等工具从邮寄延迟的作业中获取错误报告的正确方法是什么?

我尝试创建自己的延迟作业类,但Mailer.welcome()(或类似的)创建的邮件对象未正确序列化。我还尝试将error(job, exception) 方法添加到PerformableMailerPerformableMethod 类,但我相信我得到了更多通常与序列化相关的错误。我尝试了 psych 和 sych 进行连载。

【问题讨论】:

你试过这样的方法吗? ***.com/questions/12683364/… 已发布更新的解决方案,您可以检查一下吗?它最终成为一个简单的类方法而不是对象方法。 【参考方案1】:

更新的解决方案

总体而言,解决方案非常简单。如果您正在对 Object(如 MyClass.new.delay.some_method)执行延迟作业,那么您需要将错误处理定义为对象方法。如果您在 Class(如 MyTestMailer.test_email ...)上执行延迟作业,那么您需要将错误处理定义为类方法。

假设您有一个名为TestMailer 的邮件。解决方案是将错误处理定义为类方法,而不是对象方法

# Your rails mailer
class TestMailer

  # Whoa! error has to be a class method!
  def self.error(job, e)
    puts "I can now handle test mailer errors in delayed job!!!!"
  end

end

现在上面的def self.error方法将被用作延迟作业中的错误回调!

或者,如果您希望能够处理所有操作邮件错误,

class ActionMailer::Base
  def self.error(job, e)
    puts "I can now handle all mailer errors in delayed job!!!"
  end
end

原因在于 DelayedJob 的内部 PerformableMethod 处理错误的方式。 PerformableMethod 有两个东西:一个目标对象和一个目标方法。在 Action Mailer 的情况下,目标对象不是一个对象,而是您的邮件程序类TestMailer。目标方法是您使用的邮件方法,例如test_mail。 DelayedJob 查找目标对象上的所有钩子(errorbeforeafter 等)。但在我们的例子中,目标对象就是类本身。因此,钩子必须定义为类方法。

DelayedJob 处理 ActionMailer 邮件的方式有点老套。如果添加对象方法而不是类方法,则会引发不需要的异常。例如,这里是代码:

# In <delayed-job-gem>/lib/delayed/performable_method.rb
module Delayed
  class PerformableMethod

    # line #7
    delegate :method, :to => :object

ruby 中的每个对象都有一个method 函数,用于获取对该类中方法的原始引用。但是在 DelayedJob - 这个原始的method 函数已经被委托给其他一些目标对象。此 hack 使我们无法正常使用 def error 函数来处理作业错误。

编辑:添加脚注,小澄清

编辑 2:重新排序的答案

【讨论】:

很棒的反应!非常感谢! 很好的答案。如果您想跟踪 所有 个作业的错误,请参阅:***.com/a/14172132/1842747【参考方案2】:

首先,一个包含在邮件程序中的模块,可能还有其他延迟的工作:

module Delayed
  module Airbrake
    # Send error via Airbrake
    def error(job, e)
      ::Airbrake.notify(e, :component => job.name, :action => 'perform', :parameters => :job => job.inspect)
    end
 end

结束

然后包含它:

Delayed::PerformableMailer.send(:include, Delayed::Airbrake)

【讨论】:

当我尝试这样做时,我得到了这个错误:未定义的方法error' for class Class' .../gems/delayed_job-3.0.5/lib/delayed/performable_method.rb:7:in `method '

以上是关于使用延迟作业发送电子邮件时报告错误的主要内容,如果未能解决你的问题,请参考以下文章

Rails 3 延迟作业 - 升级到 Rails 3 会中断延迟作业任务

Ruby on Rails:延迟的作业无法使用邮件程序并给出路由错误

延迟作业和 Mandrill:未初始化的常量 Mandrill::API

如何使 ExceptionNotifier 在 Rails 3 中与延迟作业一起使用?

延迟作业无法在 Rails 应用程序中发送电子邮件。

Rails/Rspec:测试延迟作业邮件