workers rails perform now job generate delayed_job_active_record active ruby-on-rails-3 delayed-job exception-notification

ruby on rails 3 - perform - ¿Cómo hacer que ExceptionNotifier funcione con delayed_job en Rails 3?



sidekiq perform now (6)

Me gustaría que ExceptionNotifier envíe un correo electrónico cuando ocurra una excepción en un trabajo retrasado, al igual que para otras excepciones. ¿Cómo puedo lograr eso?


Agregando a la respuesta de @MattiasWadman, ya que exception_notification 4.0 hay una nueva forma de manejar la notificación manual . Así que en lugar de:

ExceptionNotifier::Notifier.background_exception_notification(error)

utilizar

ExceptionNotifier.notify_exception(error)


Hago esto con Rails 3.2.6, delayed_job 3.0.3 y exception_notification 2.6.1 gema

# In config/environments/production.rb or config/initializers/delayed_job.rb # Optional but recommended for less future surprises. # Fail at startup if method does not exist instead of later in a background job [[ExceptionNotifier::Notifier, :background_exception_notification]].each do |object, method_name| raise NoMethodError, "undefined method `#{method_name}'' for #{object.inspect}" unless object.respond_to?(method_name, true) end # Chain delayed job''s handle_failed_job method to do exception notification Delayed::Worker.class_eval do def handle_failed_job_with_notification(job, error) handle_failed_job_without_notification(job, error) # only actually send mail in production if Rails.env.production? # rescue if ExceptionNotifier fails for some reason begin ExceptionNotifier::Notifier.background_exception_notification(error) rescue Exception => e Rails.logger.error "ExceptionNotifier failed: #{e.class.name}: #{e.message}" e.backtrace.each do |f| Rails.logger.error " #{f}" end Rails.logger.flush end end end alias_method_chain :handle_failed_job, :notification end

Probablemente sea una buena idea cargar este código en todos los entornos para detectar errores después de la actualización del paquete, etc., antes de que lleguen a producción. Hago esto teniendo un archivo config/initializers/delayed_job.rb pero podría duplicar el código para cada config/environments/* .

Otra sugerencia es ajustar la configuración del trabajo retrasado un poco como predeterminado, puede recibir muchos correos de excepción duplicados cuando el trabajo falla.

# In config/initializers/delayed_job_config.rb Delayed::Worker.max_attempts = 3

Actualización Tuve algunos problemas con el demonio delayed_job saliendo silenciosamente y resultó ser cuando ExceptionNotifier no puede enviar correo y nadie rescató la excepción. Ahora el código se rescata y se registran.


Otra forma de manejar las excepciones (poner como inicializador):

class DelayedErrorHandler < Delayed::Plugin callbacks do |lifecycle| lifecycle.around(:invoke_job) do |job, *args, &block| begin block.call(job, *args) rescue Exception => e # ...Process exception here... raise e end end end end Delayed::Worker.plugins << DelayedErrorHandler


Para exception_notification 3.0.0 cambio:

ExceptionNotifier::Notifier.background_exception_notification(error)

a:

ExceptionNotifier::Notifier.background_exception_notification(error).deliver


Respuesta más sencilla y actualizada:

Delayed::Job.enqueue (JS=Struct.new(:a){ def perform; raise ''here''; end }).new(1)

Y prueba en consola con:

# In config/initializers/delayed_job.rb module CustomFailedJob def handle_failed_job(job, error) super ExceptionNotifier.notify_exception(error, data: {job: job}) end end class Delayed::Worker prepend CustomFailedJob end


alias_method_chain ya no existe en Rails 5.

Aquí está la nueva forma (apropiada) de hacerlo usando el prepend Ruby 2

# Chain delayed job''s handle_failed_job method to do exception notification Delayed::Worker.class_eval do def handle_failed_job_with_notification job, error handle_failed_job_without_notification job, error ExceptionNotifier.notify_exception error, data: {job: job, handler: job.handler} rescue nil end alias_method_chain :handle_failed_job, :notification end