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