2012-01-18 15 views
12

Ho un'app Rails 3 in produzione con Passenger su Apache. Ho questo codice:Utilizzo di fork in Ruby on Rails per la creazione di processi paralleli

class Billing < ActiveRecord::Base 
    after_save :sendEmails 

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

In localhost, quando l'applicazione crea una fatturazione, dopo che è stato salvato, l'applicazione invia una e-mail per l'utente, tutto funziona bene. Ma nel server, dopo che l'app crea una fatturazione, mi getta errori relativi alla gemma MySQL2, errori come "Il server MySQL è andato via" o "Connessione persa" e l'app non invia le email. Se rimuovo la forcella funziona correttamente, ma voglio usare fork, voglio creare un processo separato perché richiede molto tempo quando si inviano email. Quale potrebbe essere il problema?

risposta

17

Il problema è che un processo di fork eredita alcune delle risorse del suo genitore, come i suoi descrittori di file. In particolare una di queste risorse condivise è la connessione MySQL. Quando il processo figlio termina l'invio e l'uscita dell'e-mail, chiude la connessione MySQL, che chiude la connessione dei processi principali.

Se fate continuare su questa strada (ed è frought con sottigliezze simili) allora avete bisogno di fare qualcosa di simile

::ActiveRecord::Base.clear_all_connections! 

Prima di forchetta e

::ActiveRecord::Base.establish_connection 

seguito. Dovrai fare qualcosa di simile con servizi come memcached o mongodb se li usi.

+0

sai quali risorse sono ereditate? Pensavo che un fork di processo copi l'intero processo? non è l'intero ambiente delle rotaie caricato di nuovo su una forcella? –

+1

Copia l'intero processo, ma i descrittori di file si riferiscono esattamente allo stesso file (vedere la pagina man per fork) –

+0

Ho trovato che 'establish_connection' non è sempre necessario, dato che ActiveRecord di solito gestirà questo in modo trasparente. – spume

9

Prestare estrema attenzione quando si utilizza la forcella con le guide/passeggero, può diventare molto caotico! Invece, dovresti usare resque or delayed_job per questa attività!

+2

ho preso 7 giorni per scoprire che il msg di errore "Mysql :: Errore: Connessione persa a MySQL server durante la query" e "MySQL :: Errore : Il server MySQL è andato via "era un risultato dell'uso della forcella. –

2

È possibile ristabilire il collegamento all'interno della forcella:

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