2009-05-22 30 views
28

Cuando se crea un nuevo recurso y tiene que hacer un poco de un procesamiento más largo antes de que el recurso está listo, ¿Cómo envío que el procesamiento de distancia en el fondo donde no se puede sostener la solicitud actual u otro el tráfico a mi aplicación web?Ruby on Rails: ¿Cómo ejecutar cosas en segundo plano?

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 

Respuesta

39

Usted debería salir los siguientes Railscasts:

explican cómo ejecutar los procesos de fondo en los carriles en cada posible manera (con o sin aq ueue ...)

+2

En estos días, los/las opciones con más seguidores más utilizados son [sidekiq] (https://github.com/mperham/sidekiq), [resque ] (https://github.com/defunkt/resque), y [demorado_trabajo] (https://github.com/collectiveidea/delayed_job). En mi humilde opinión, Sidekiq es el mejor para colas de alto rendimiento, y el retraso de trabajo es el mejor para un rendimiento muy bajo. –

+0

Otra opción es [IronWorker] (http://www.iron.io) si desea procesar en segundo plano "como un servicio" y nunca tener que preocuparse por la idea de servidores o cola. IronMQ/IronWorker también ofrece reintentos automáticos, registros de tareas, webhooks, etc. Se integra muy bien con Rails. Aquí hay algunos videos: https://www.youtube.com/user/ironiodevelopers – Chad

7

iniciar un proceso separado, que es probablemente el más fácil de hacer con system, anteponiendo un 'nohup' y añadiendo una '&' al final del comando se le pasa. (Asegúrese de que el comando es sólo un argumento de cadena, no una lista de argumentos.)

Hay varias razones que desea hacerlo de esta manera, en lugar de, por ejemplo, tratando de utilizar hilos:

  1. Los subprocesos 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 causen que todo el proceso se bloquee.

  2. Si ejecuta un programa con un nombre diferente, es fácilmente identificable en 'ps', por lo que no accidentalmente piensa que se trata de un FastCGI que se ha vuelto loco o algo así, y lo mata.

En realidad, el proceso se inicia debe ser "deamonized", consulte la clase Daemonize en busca de ayuda.

2

idealmente desea utilizar un servidor de trabajos en segundo plano existente, en lugar de escribir uno propio. estos generalmente le permitirán enviar un trabajo y darle una clave única; A continuación, puede usar la tecla para consultar periódicamente el servidor de trabajos para conocer el estado de su trabajo sin bloquear su aplicación web. here is a nice roundup de las diversas opciones disponibles.

0

¿Qué hay de:

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 ejecute en otro proceso y tendrán acceso a ActiveRecord, pudiendo acceder a la base de datos.

1

Me gusta usar backgroundrb, es agradable, te permite comunicarte durante largos procesos. Para que pueda tener actualizaciones de estado en su aplicación de raíles

1

Creo que spawn es una excelente manera de bifurcar su proceso, hacer algo de procesamiento en segundo plano, y mostrar al usuario solo una confirmación de que se inició este proceso.

6

¡He estado experimentando con la gema 'delayed_job' porque funciona con la plataforma de alojamiento Heroku y fue ridículamente fácil de configurar !!

Añadir joya para Gemfile, bundle install, rails g delayed_job, rake db:migrate A continuación, iniciar un controlador de cola con;

RAILS_ENV=production script/delayed_job start 

donde se tiene una llamada a un método, que es su largo proceso es decir

company.send_mail_to_all_users 

lo cambia a;

company.delay.send_mail_to_all_users 

Comprobar los documentos completos en GitHub: https://github.com/collectiveidea/delayed_job