2010-07-22 13 views
53

Retrasado :: La función de reintento automático del trabajo es excelente, pero hay un trabajo que deseo reintentar manualmente ahora. ¿Existe algún método al que pueda llamar en el trabajo como ...Reintentar manualmente el trabajo en Delayed_job

Delayed::Job.all[0].perform 

o ejecutar, o algo así. Probé algunas cosas y analicé la documentación, pero no pude encontrar la manera de ejecutar un intento manual de un trabajo.

+2

'Retrasado :: Worker.new.run (Delayed :: Job.first)' [ref] (http://stackoverflow.com/a/20146200/495132) –

Respuesta

88

Para llamar manualmente un trabajo

Delayed::Job.find(10).invoke_job # 10 is the job.id 

Esto no elimina el trabajo si se ejecuta correctamente. Es necesario eliminar de forma manual:

Delayed::Job.find(10).destroy 
+10

La alternativa sugerida por @joe es mucho mejor, especialmente si el trabajo necesita saber si se está ejecutando en script/consola o dentro de un corredor de trabajo. Intente hacer cola en el trabajo para volver a intentarlo de inmediato Retraso :: Job.first.update_attributes (: attempts => 0,: run_at => Time.ahora,: failed_at => nil,: locked_by => nil,: locked_at => nil) –

+8

"intentos" no pueden ser asignados en 'update_attributes' porque es un atributo protegido. Acabo de hacer: 'dj = Retrasado :: Job.first; dj.run_at = Time.now; dj.attempts = 0; dj.save!; ' – Anjan

+0

Para hacerlo en masa esto funcionó (aproximadamente 100 trabajos) Retraso :: Job.where.all.each {| dj | dj.run_at = Time.now; dj.attempts = 0; dj.save!} – tobinharris

11

Puede hacerlo exactamente como lo dijo, encontrando el trabajo y ejecutándolo.

Sin embargo, lo que generalmente hago es simplemente configurar el run_at para que el procesador de tareas lo recupere nuevamente.

+1

No hay método 'perform' para el trabajo retrasado objeto. Lo más cercano es 'Delayed :: Job.find (10) .payload_object.perform', y uno no debería usar eso. – lulalala

8

tengo un método en un controlador para propósitos de prueba que solo restablece todos los puestos de trabajo con retraso cuando llegué a una dirección URL. No es muy elegante, pero funciona muy bien para mí:

# For testing purposes 
    def reset_all_jobs 
    Delayed::Job.all.each do |dj| 
     dj.run_at = Time.now - 1.day 
     dj.locked_at = nil 
     dj.locked_by = nil 
     dj.attempts = 0 
     dj.last_error = nil 
     dj.save 
    end 
    head :ok 
    end 
+1

use update_all ... es una llamada al db. – baash05

+1

No puede usar update_all ebcause los intentos están protegidos atributo –

+1

update_all usa SQL directamente y por lo tanto no invoca validaciones (o atributos protegidos, etc.) – Michael

4

En un entorno de desarrollo, a través de rails console, siguiendo la sugerencia de Joe Martínez, una buena manera de volver a intentar todos los trabajos de retraso es:

Delayed::Job.all.each{|d| d.run_at = Time.now; d.save!} 
+5

Actualizar 'run_at' en 4.0.1 no parece ser suficiente. Tuve que hacer lo siguiente: 'Delayed :: Job.where (" failed_at no es nulo "). Cada do | dj | dj.run_at = Time.now; dj.last_error = nil; dj.failed_at = nil; dj.save! end' – steakchaser

6

respuestas previas anteriores podría estar desactualizado He encontrado que necesitaba para establecer failed_at, locked_by y locked_at a cero:

(para cada trabajo que desea volver a intentar):

d.last_error = nil 
d.run_at = Time.now 
d.failed_at = nil 
d.locked_at = nil 
d.locked_by = nil 
d.attempts = 0 
d.failed_at = nil # needed in Rails 5/delayed_job (4.1.2) 
d.save! 
1
Delayed::Job.all.each(&:invoke_job) 
21
Delayed::Worker.new.run(Delayed::Job.last) 

Esto eliminará el trabajo después de que se hecho.

+0

Lo eliminará incluso si falla – aledustet

+0

Para todo el trabajo retrasado puede hacer 'Delayed :: Job.find_each (batch_size: 100) {| d | Retrasado :: Worker.new.run (d)} ' – MatayoshiMariano

3

si ha fallado trabajo retrasado los que es necesario volver a ejecutar, a continuación, tendrá que seleccionar solamente ellos y establece que todo se refiere a reintento fallado en nulo:

Delayed::Job.where("last_error is not null").each do |dj| 
    dj.run_at = Time.now.advance(seconds: 5) 
    dj.locked_at = nil 
    dj.locked_by = nil 
    dj.attempts = 0 
    dj.last_error = nil 
    dj.failed_at = nil 
    dj.save 
end 
0

poner esto en un fichero de inicialización!

module Delayed 
    module Backend 
    module ActiveRecord 
     class Job 
     def retry! 
      self.run_at = Time.now - 1.day 
      self.locked_at = nil 
      self.locked_by = nil 
      self.attempts = 0 
      self.last_error = nil 
      self.failed_at = nil 
      self.save! 
     end 
     end 
    end 
    end 
end 

continuación, puede ejecutar Delayed::Job.find(1234).retry!

Esto se adhieren básicamente el trabajo de nuevo en la cola y procesarlo con normalidad.

Cuestiones relacionadas