tutorial - Ruby on Rails: ¿Cómo ejecutar cosas en segundo plano?
rails job work (7)
Cuando se crea un nuevo recurso y necesita realizar un procesamiento prolongado antes de que el recurso esté listo, ¿cómo puedo enviar ese procesamiento a un segundo plano donde no retendrá la solicitud actual u otro tráfico a mi aplicación web?
en mi modelo:
class User < ActiveRecord::Base
after_save :background_check
protected
def background_check
# check through a list of 10000000000001 mil different
# databases that takes approx one hour :)
if( check_for_record_in_www( self.username ) )
# code that is run after the 1 hour process is finished.
user.update_attribute( :has_record )
end
end
end
¡Acabo de experimentar con la gema ''delayed_job'' porque funciona con la plataforma de hospedaje Heroku y fue ridículamente fácil de configurar!
Agregue gema a Gemfile, bundle install
, rails g delayed_job
, rake db:migrate
rails g delayed_job
Luego inicie un controlador de cola con;
RAILS_ENV=production script/delayed_job start
Donde tiene un método de llamada que es su proceso largo es decir
company.send_mail_to_all_users
lo cambias a
company.delay.send_mail_to_all_users
Compruebe la documentación completa en github: delayed_job
Comience un proceso separado, que probablemente se hace más fácilmente con el system
, anteponiendo un ''nohup'' y agregando un ''&'' al final del comando que lo pasa. (Asegúrese de que el comando sea solo un argumento de cadena, no una lista de argumentos).
Hay varias razones por las que desea hacerlo de esta manera, en lugar de, digamos, tratar de usar subprocesos:
Los hilos de Ruby pueden ser un poco complicados cuando se trata de hacer E / S; Tienes que tener cuidado de que algunas cosas que haces no bloqueen todo el proceso.
Si ejecuta un programa con un nombre diferente, es fácilmente identificable en ''ps'', por lo que no cree accidentalmente que sea un back-end FastCGI que se haya vuelto loco o algo así, y lo mate.
En realidad, el proceso que inicie debe estar "desmitificado", consulte la clase Daemonize para obtener ayuda.
Creo que spawn es una excelente manera de dividir tu proceso, hacer un procesamiento en segundo plano y mostrarle al usuario solo una confirmación de que se inició este procesamiento.
Definitivamente deberías revisar los siguientes Railscasts:
- http://railscasts.com/episodes/127-rake-in-background
- http://railscasts.com/episodes/128-starling-and-workling
- http://railscasts.com/episodes/129-custom-daemon
- http://railscasts.com/episodes/366-sidekiq
Explican cómo ejecutar procesos en segundo plano en Rails de todas las formas posibles (con o sin cola ...)
Me gusta usar backgroundrb, es bueno que te permite comunicarte durante largos procesos. Para que pueda tener actualizaciones de estado en su aplicación Rails
Qué pasa:
def background_check
exec("script/runner check_for_record_in_www.rb #{self.username}") if fork == nil
end
El programa " check_for_record_in_www.rb
" se ejecutará en otro proceso y tendrá acceso a ActiveRecord, pudiendo acceder a la base de datos.
lo ideal es utilizar un servidor de trabajo en segundo plano existente, en lugar de escribir el suyo propio. estos normalmente te permitirán enviar un trabajo y darle una clave única; luego puede usar la tecla para consultar periódicamente el estado de su trabajo a jobserver sin bloquear su aplicación web. Aquí hay un buen resumen de las diversas opciones que hay.