2012-01-18 15 views
12

Tengo una aplicación Rails 3 en producción con Passenger on Apache. Tengo este código:Uso de un tenedor en Ruby on Rails para crear el proceso paralelo

class Billing < ActiveRecord::Base 
    after_save :sendEmails 

    private 
    def sendEmails 
     fork do 
     UserMailer.clientBilling(self.user, self).deliver 
     end 
    end 
end 

En localhost, cuando la aplicación crea una factura, una vez guardado, la aplicación envía un correo electrónico al usuario, todo funciona bien. Pero en el servidor, después de que la aplicación crea una factura, me arroja errores relacionados con la gema MySQL2, errores como "El servidor MySQL se ha ido" o "Conexión perdida", y la aplicación no envía los correos electrónicos. Si elimino la horquilla, funciona bien, pero quiero usar horquilla, quiero crear un proceso separado porque tarda mucho en enviar correos electrónicos. ¿Cual podría ser el problema?

Respuesta

17

El problema es que un proceso bifurcado hereda algunos de los recursos de sus padres, como sus descriptores de archivos. En particular, uno de esos recursos compartidos es la conexión MySQL. Cuando el proceso secundario finaliza su envío y salida de correo electrónico, cierra la conexión MySQL, que cierra la conexión de procesos principal.

Si lo hace seguir por este camino (y es frought con sutilezas similares), entonces usted tiene que hacer algo como

::ActiveRecord::Base.clear_all_connections! 

Antes de tenedor y

::ActiveRecord::Base.establish_connection 

después. Tendrás que hacer algo similar con servicios como memcached o mongodb si los usas.

+0

¿sabes qué recursos se heredan? Pensé que un fork de proceso copiaba todo el proceso. ¿No está todo el entorno de los rieles cargado de nuevo en un tenedor? –

+1

Copia todo el proceso, pero los descriptores de archivo hacen referencia al mismo archivo (consulte la página de manual para el tenedor) –

+0

He descubierto que 'establish_connection' no siempre es necesario ya que ActiveRecord generalmente lo administra de forma transparente. – spume

9

Tenga mucho cuidado al usar un tenedor con rieles/pasajero, ¡puede llegar a ser muy complicado! ¡En su lugar, debe usar resque or delayed_job para esta tarea!

+2

Me tomó 7 días para descubrir que el error msg "MySQL :: Error: Se perdió la conexión al servidor MySQL durante la consulta" y "Error MySQL :: : El servidor MySQL se ha ido "fue el resultado del uso de un tenedor. –

2

Puede restablecer la conexión interior del tenedor:

dbconfig = YAML::load(File.open('your_app_dir/config/database.yml')) 
ActiveRecord::Base.establish_connection(dbconfig['development'])