11

Tenemos que usar el trabajo demorado (o algún otro procesador de fondo de trabajo) para ejecutar trabajos en segundo plano, pero no podemos cambiar las secuencias de arranque/arranque -levels en el servidor. Esto significa que no se garantiza que el daemon permanezca disponible si el proveedor reinicia el servidor (ya que el daemon se habría iniciado con una receta capistrano que solo se ejecuta una vez por implementación).Comience o asegúrese de que la tarea retrasada se ejecuta cuando una aplicación/servidor se reinicia

Actualmente, la mejor manera en que puedo pensar para asegurarme de que el demonio delayed_job siempre se está ejecutando, es agregar un inicializador a nuestra aplicación Rails que comprueba si el daemon se está ejecutando. Si no se está ejecutando, el inicializador inicia el daemon, de lo contrario, simplemente lo deja.

La pregunta, por lo tanto, es ¿cómo detectamos que el daemon Delayed_Job se ejecuta desde dentro de un script? (Deberíamos ser capaces de iniciar un daemon con bastante facilidad, pero no sé cómo detectar si uno ya está activo).

¿Alguien tiene alguna idea?

Saludos, Bernie

Sobre la base de la respuesta de abajo, esto es lo que ocurrió. Sólo hay que poner en config/inicializadores y ya está todo listo:

#config/initializers/delayed_job.rb 

DELAYED_JOB_PID_PATH = "#{Rails.root}/tmp/pids/delayed_job.pid" 

def start_delayed_job 
    Thread.new do 
    `ruby script/delayed_job start` 
    end 
end 

def process_is_dead? 
    begin 
    pid = File.read(DELAYED_JOB_PID_PATH).strip 
    Process.kill(0, pid.to_i) 
    false 
    rescue 
    true 
    end 
end 

if !File.exist?(DELAYED_JOB_PID_PATH) && process_is_dead? 
    start_delayed_job 
end 
+0

En su respuesta, ¿no deberíamos también suministrar '-e production'? – nathanvda

+0

Usando rails3 esta solución no funciona para mí. Comenzar el proceso va completamente mal: sigue empezando trabajos adicionales. Estoy de vuelta a las tareas de capistrano :) – nathanvda

Respuesta

5

comprobar la existencia del archivo demonios PID (File.exist? ...). Si está allí, entonces suponga que está funcionando, de lo contrario, enciéndalo.

+0

¡Genial! ¡Suena fácil! ¿Pasaría a donde puedo encontrar ese archivo? – btelles

+1

Encontrará el archivo en la carpeta tmp/pids de su aplicación. También es posible que desee comprobar si existe un proceso con la ID del archivo. El archivo PID puede existir después de un bloqueo. –

+0

¡Excelente! ¡Gracias! Voy a votar por ahora, y esperar a ver si hay otras alternativas para un día o 2. – btelles

9

Algunas ideas más sobre limpieza: El "comenzar" no es necesario. Debería rescatar "ningún proceso de este tipo" para no iniciar nuevos procesos cuando algo más vaya mal. Rescatar "ningún archivo o directorio" así como simplificar la condición.

DELAYED_JOB_PID_PATH = "#{Rails.root}/tmp/pids/delayed_job.pid" 

def start_delayed_job 
    Thread.new do 
    `ruby script/delayed_job start` 
    end 
end 

def daemon_is_running? 
    pid = File.read(DELAYED_JOB_PID_PATH).strip 
    Process.kill(0, pid.to_i) 
    true 
rescue Errno::ENOENT, Errno::ESRCH # file or process not found 
    false 
end 

start_delayed_job unless daemon_is_running? 

Tenga en cuenta que este código no funcionará si inicia más de un trabajador. Y revisa el argumento "-m" de script/retardado_que genera un proceso de monitor junto con el daemon (s).

0

Gracias por la solución proporcionada en la pregunta (y la respuesta que la inspiró :-)), funciona para mí, incluso con varios trabajadores (Rails 3.2.9, Ruby 1.9.3p327).

Me preocupa que me olvide de reiniciar el trabajo retrasado después de hacer algunos cambios en lib, por ejemplo, lo que hace que me depure durante horas antes de darme cuenta de eso.

que añade lo siguiente a mi archivo script/rails con el fin de permitir que el código proporcionado en la pregunta para ejecutar cada vez que comenzamos rieles, pero no cada vez que un trabajador empieza:

puts "cleaning up delayed job pid..." 
dj_pid_path = File.expand_path('../../tmp/pids/delayed_job.pid', __FILE__) 
begin 
    File.delete(dj_pid_path) 
rescue Errno::ENOENT # file does not exist 
end 
puts "delayed_job ready." 

Un pequeño inconveniente de que yo' Sin embargo, m con esto es que también se llama con rails generate por ejemplo. No pasé mucho tiempo buscando una solución para eso, pero las sugerencias son bienvenidas :-)

Tenga en cuenta que si está usando unicornio, es posible que desee agregar el mismo código a config/unicorn.rb antes de la llamada before_fork.

- Editado: Después de jugar un poco más con las soluciones anteriores, terminé haciendo lo siguiente:

he creado un archivo con el contenido script/start_delayed_job.rb:

puts "cleaning up delayed job pid..." 
dj_pid_path = File.expand_path('../../tmp/pids/delayed_job.pid', __FILE__) 

def kill_delayed(path) 
    begin 
    pid = File.read(path).strip 
    Process.kill(0, pid.to_i) 
    false 
    rescue 
    true 
    end 
end 

kill_delayed(dj_pid_path) 

begin 
    File.delete(dj_pid_path) 
rescue Errno::ENOENT # file does not exist 
end 

# spawn delayed 
env = ARGV[1] 
puts "spawing delayed job in the same env: #{env}" 

# edited, next line has been replaced with the following on in order to ensure delayed job is running in the same environment as the one that spawned it 
#Process.spawn("ruby script/delayed_job start") 
system({ "RAILS_ENV" => env}, "ruby script/delayed_job start") 

puts "delayed_job ready." 

Ahora Puedo solicitar este archivo en cualquier lugar que desee, incluyendo 'script/rails' y 'config/unicorn.rb' haciendo:

# in top of script/rails 
START_DELAYED_PATH = File.expand_path('../start_delayed_job', __FILE__) 
require "#{START_DELAYED_PATH}" 

# in config/unicorn.rb, before before_fork, different expand_path 
START_DELAYED_PATH = File.expand_path('../../script/start_delayed_job', __FILE__) 
require "#{START_DELAYED_PATH}" 
0

no es bueno, pero funciona

aviso legal: digo que no es genial porque esto provoca un reinicio periódico, que para muchos no será deseable. Y simplemente intentar comenzar puede causar problemas porque la implementación de DJ puede bloquear la cola si se crean instancias duplicadas.

Puede programar cron tareas que se ejecutan periódicamente para iniciar los trabajos en cuestión. Como DJ trata los comandos de inicio como no operativos cuando el trabajo ya se está ejecutando, simplemente funciona. Este enfoque también se ocupa del caso en el que DJ muere por algún motivo que no sea un reinicio del host.

# crontab example 
0 * * * * /bin/bash -l -c 'cd /var/your-app/releases/20151207224034 && RAILS_ENV=production bundle exec script/delayed_job --queue=default -i=1 restart' 

Si está utilizando una joya como whenever esto es bastante sencillo.

every 1.hour do 
    script "delayed_job --queue=default -i=1 restart" 
    script "delayed_job --queue=lowpri -i=2 restart" 
end 
Cuestiones relacionadas