Error reporting when sending emails with delayed_job

前端 未结 2 2219
长情又很酷
长情又很酷 2021-02-20 15:12

What\'s the proper way to get error reports, when using a tool like AirBrake or ExceptionNotifier from mailing delayed jobs?

I tried to creating my own delayed job class

相关标签:
2条回答
  • 2021-02-20 15:37

    First, a module for inclusion in mailer and, possibly, other delayed jobs:

    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
    

    end

    then include it:

    Delayed::PerformableMailer.send(:include, Delayed::Airbrake)
    
    0 讨论(0)
  • 2021-02-20 15:39

    Updated Solution

    Overall the solution is quite simple. If you have are doing delayed_job on an Object (like MyClass.new.delay.some_method), then you need to define error handling as an object method. If you're doing delayed_job on a Class (like MyTestMailer.test_email ...), then you need to define error handling as a class method.

    Let's say you have a mailer called TestMailer. The solution is to define the error handling as a class method, not an object method:

    # 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
    

    Now the above def self.error method will be used as the error callback in the delayed job!

    Or if you want to be able to handle all action mailer errors,

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

    The reason is because of the way DelayedJob's internal PerformableMethod handles errors. A PerformableMethod has two things: a Target Object, and a Target Method. In Action Mailer's case, the Target Object is not an object, but your mailer class TestMailer. The target method is the mail method that you use, say test_mail. DelayedJob looks for all the hooks (error, before, after, etc) on the Target Object. But in our case, the Target Object is the class itself. Hence the hooks have to be defined as class methods.

    The way DelayedJob handles ActionMailer mails is a little hacky. If you add an object method instead of a class method, it throws an unwanted exception. For example, here is the code:

    # In <delayed-job-gem>/lib/delayed/performable_method.rb
    module Delayed
      class PerformableMethod
    
        # line #7
        delegate :method, :to => :object
    

    Every object in ruby has a method function, which is used to get a raw reference to a method inside that class. But in DelayedJob - this raw method function has been kind of delegated to some other target object. This hack prevents us from normally using the def error function for handling job errors.

    Edit: Added footnote, minor clarification

    Edit 2: Reordered answer

    0 讨论(0)
提交回复
热议问题