ruby on rails - sleep_delay - Delayed_job no ejecuta el método de ejecución pero vacía la cola de trabajos
rails job work (6)
Tengo una nueva aplicación de Rails 3, aquí está mi Gemfile:
source ''http://rubygems.org''
gem ''rails'', ''3.0.0'' gem ''delayed_job''
gem ''sqlite3-ruby'', :require => ''sqlite3''
Aquí está la clase que representa el trabajo que quiero poner en cola:
class Me < Struct.new(:something)
def perform
puts "Hello from me"
logger.info "Hello from me"
logger.debug "Hello from me"
raise Exception.new
end
end
Desde la consola sin trabajadores corriendo:
irb(main):002:0> Delayed::Job.enqueue Me.new(1)
=> #<Delayed::Backend::ActiveRecord::Job id: 7, priority: 0, attempts: 0, handler: "--- !ruby/struct:Me /nsomething: 1/n", last_error: nil, run_at: "2010-12-29 07:24:11", locked_at: nil, failed_at: nil, locked_by: nil, created_at: "2010-12-29 07:24:11", updated_at: "2010-12-29 07:24:11">
Como he mencionado: no hay trabajadores que se ejecutan:
irb(main):003:0> Delayed::Job.all
=> [#<Delayed::Backend::ActiveRecord::Job id: 7, priority: 0, attempts: 0, handler: "--- !ruby/struct:Me /nsomething: 1/n", last_error: nil, run_at: "2010-12-29 07:24:11", locked_at: nil, failed_at: nil, locked_by: nil, created_at: "2010-12-29 07:24:11", updated_at: "2010-12-29 07:24:11">]
Comienzo un trabajador con script/delayed_job run
La cola se vacía:
irb(main):006:0> Delayed::Job.all
=> []
Sin embargo, nada sucede como resultado de las puts
, no se registra nada de las llamadas del logger
y no se genera ninguna excepción. Apreciaría cualquier ayuda / conocimiento o cualquier cosa para probar.
¿Qué versión de delayed_job está ejecutando?
Necesita la rama 2.1 en https://github.com/collectiveidea/delayed_job para Rails 3.0 y superior.
Acabo de copiar tu clase en irb y traté de hacerlo Me.new.perform
:
Hello from me
NameError: undefined local variable or method `logger'' for #<struct Me something=nil>
from (irb):6:in `perform''
from (irb):14
¿Tu clase tiene acceso a ''logger''?
¿Podría intentar hacer otra cosa, como abrir y escribir en un archivo?
File.open("testing.txt", ''w'') {|f| f.write("hello") }
Tenga en cuenta que el comando de "poner" del trabajador con retraso se enviará a su salida estándar por lo que probablemente nunca verá esto. Y si desea realizar cualquier registro, creo que debe crear una nueva instancia de Logger dentro de su método de ejecución para poder hacerlo.
Ben W tiene toda la razón, asegúrate de tener un archivo bajo
"#{Rails.root}/config/initializers/delayed_job_worker.rb"
Esto define cómo debe comportarse el trabajador. El trabajador solo va a quitar silenciosamente los errores de lo contrario.
Una vez que haga esto, debería poder averiguar más sobre su error. Para mi ejemplo, estaba usando delayed_job_mongoid, así que esto agregó una entrada de "last_error" (que creo que deberías tener en tu tabla mysql para delayed_job independientemente ...)
Y como concluyó Ben W, debe asegurarse de que el objeto que está creando sea conocido para la aplicación (o para el trabajador). Mi problema era que estaba en la consola Rails probando un objeto de clase. El trabajador no sabía de esta clase, por lo que se despidió.
En mi archivo application.rb:
module TextSender
class Application < Rails::Application
require "#{Rails.root.to_s}/lib/SendTextJob.rb"
y mi archivo lib:
class SendTextJob < Struct.new(:text, :number)
def perform
Rails.logger.info "Sending #{text} to #{number}"
puts "Successfully sent text"
end
end
Entonces corriendo
Delayed::Job.enqueue SendTextJob.new("Work on this text NOW, please?", "5551231234")
Se confirmó en mi archivo log / development.log que esto tuvo éxito. También probé la creación y el objeto (un objeto de usuario o cualquier modelo que pueda tener) en este método de ejecución, y funcionó.
Por defecto, delayed_job destruye trabajos fallidos:
Entonces, el primer paso es configurar un inicializador y desactivar ese comportamiento
Delayed::Worker.destroy_failed_jobs = false
Además, si se produce un error de deserialización, es un error instantáneo del trabajo.
Esto provoca la eliminación del trabajo (si no lo ha eliminado).
Así que intente agregar lo siguiente alrededor de la línea 120 de worker.rb
rescue DeserializationError => error
say "DeserializationError: #{error.message}"
job.last_error = "{#{error.message}/n#{error.backtrace.join(''/n'')}"
failed(job)
Es bastante inútil, pero al menos sabrá que es un error de deserialización.
Terminé usando el trabajo w. Método de ejecución (). Mucho más confiable. También recuerde colocar su definición de trabajo como un archivo separado para que el cargador de clases pueda encontrarla cuando se esté ejecutando (en lugar de simplemente incluir la definición de clase en su modelo en algún lugar).
Tuve este problema y descubrí que se debía a que los archivos de Rails 3 en el directorio lib/
no están cargados automáticamente. Para diagnosticar, he añadido:
# application.rb
Delayed::Worker.destroy_failed_jobs = false
como lo mencionó Ben W. Esto me dijo lo que estaba pasando, ya que podía inspeccionar el last_error
.
Entonces, para resolver el problema de la carga automática, encontré un par de respuestas en SO, pero lo esencial es agregar esto:
# application.rb
# Custom directories with classes and modules you want to be autoloadable.
# config.autoload_paths += %W(#{config.root}/extras)
config.autoload_paths += %W(#{config.root}/lib)
config.autoload_paths += Dir["#{config.root}/lib/**/"]
El cual fue provisto amablemente por http://hemju.com/2010/09/22/rails-3-quicktip-autoload-lib-directory-including-all-subdirectories/ .
Me interesaría ver cómo podría resolver esto sin activar la carga automática para el directorio lib. ¿Alguna idea?
verifique los registros, debería ver algo sobre los mensajes de DelayedJob, al menos qué trabajo se inicia y cuál es su estado de salida
en una terminal, lance:
tail -f log/development.log
luego vuelva a intentarlo desde una consola de rieles para verificar qué sucede al hacer una consulta simple de ActiveRecord y luego usar DelayedJob. Puedes leer lo que está registrado en el otro terminal.
Saludos, A.