work sleep_delay rails perform method job delayed_job_active_record delayed_job delayed daemonize active ruby-on-rails ruby-on-rails-3 delayed-job

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.



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.