使用delayed_job发送电子邮件时报告错误

时间:2012-08-01 19:41:01

标签: ruby-on-rails-3 delayed-job error-reporting airbrake exception-notifier

使用AirBrake或ExceptionNotifier等工具发送延迟作业时,获取错误报告的正确方法是什么?

我尝试创建自己的延迟作业类,但Mailer.welcome()(或类似)创建的邮件对象未正确序列化。我还尝试在error(job, exception)PerformableMailer类中添加PerformableMethod方法,但我认为通常与序列化相关的错误更多。我为序列化尝试了psych和sych。

2 个答案:

答案 0 :(得分:7)

更新的解决方案

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

假设您有一封名为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函数已被委托给其他一些目标对象。这种破解使我们无法正常使用def error函数来处理作业错误。

编辑:添加脚注,轻微澄清

编辑2:重新排序的答案

答案 1 :(得分: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)