2012-01-18 20 views
12

Mam aplikację Rails 3 w produkcji z Passenger na Apache. Mam ten kod:Używanie fork w Ruby on Rails do tworzenia równoległego procesu

class Billing < ActiveRecord::Base 
    after_save :sendEmails 

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

W localhost, gdy aplikacja tworzy rozliczenia, po jego zapisaniu, aplikacja wysyła wiadomość e-mail do użytkownika, wszystko działa bez zarzutu. Ale na serwerze, po tym, jak aplikacja tworzy fakturę, wyrzuca mi błędy związane z klejnotem MySQL2, błędy takie jak "Serwer MySQL zniknął" lub "Połączenie zgubione", a aplikacja nie wysyła e-maili. Jeśli wyjmę widelec, działa dobrze, ale chcę użyć rozwidlenia, chcę utworzyć oddzielny proces, ponieważ trwa to długo podczas wysyłania wiadomości e-mail. Jaki może być problem?

Odpowiedz

17

Problem polega na tym, że rozwidlony proces dziedziczy niektóre zasoby rodzica, takie jak deskryptory plików. W szczególności jednym z takich udostępnionych zasobów jest połączenie MySQL. Gdy proces potomny zakończy wysyłanie i wychodzenie wiadomości e-mail, zamyka połączenie MySQL, które zamyka połączenie procesów macierzystych.

Jeśli tak dalej tą drogą (i to frought o podobnej subtelności) to trzeba zrobić coś jak

::ActiveRecord::Base.clear_all_connections! 

przed wami widelcem i

::ActiveRecord::Base.establish_connection 

później. Będziesz musiał zrobić coś podobnego z usługami takimi jak memcached lub mongodb, jeśli ich używasz.

+0

Czy wiesz, które zasoby są dziedziczone? Myślałem, że fork procesu kopiuje cały proces? czy całe środowisko szyn nie jest ponownie ładowane na widelec? –

+1

Kopiuje cały proces, ale deskryptory plików odwołują się do tego samego pliku (zobacz stronę podręcznika dla widelca). –

+0

Zauważyłem, że 'ustanowienie_łączenia' nie zawsze jest konieczne, ponieważ ActiveRecord zwykle zarządza tym w sposób przezroczysty. – spume

9

Należy zachować szczególną ostrożność podczas korzystania z widelca z szynami/pasażera, ponieważ może to bardzo zabrudzić! Zamiast tego do tego zadania powinieneś użyć resque or delayed_job!

+2

wziąłem 7 dni, aby odkryć, że MSG błąd "Mysql :: Error: Utracono połączenie z serwerem MySQL podczas kwerendy" i „Mysql :: Error : Serwer MySQL zniknął "był wynikiem użycia widelca. –

2

można ponownie nawiązać połączenie wewnątrz widełek:

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