Использование fork в Ruby on Rails для создания параллельного процесса
У меня есть приложение Rails 3 с пакетом Passenger на Apache. У меня есть этот код:
class Billing < ActiveRecord::Base
after_save :sendEmails
private
def sendEmails
fork do
UserMailer.clientBilling(self.user, self).deliver
end
end
end
В localhost, когда приложение создает биллинг, после его сохранения приложение отправляет электронное письмо пользователю, все работает нормально. Но на сервере после того, как приложение создает биллинг, оно выдает мне ошибки, связанные с gem MySQL2, ошибки, такие как "сервер MySQL ушел" или "соединение потеряно", и приложение не отправляет электронные письма. Если я удаляю вилку, она работает нормально, но я хочу использовать fork, я хочу создать отдельный процесс, потому что он длится долго при отправке писем. В чем может быть проблема?
Ответы
Ответ 1
Проблема заключается в том, что разветвленный процесс наследует некоторые из его родительских ресурсов, например, его файловые дескрипторы. В частности, одним из таких общих ресурсов является соединение MySQL. Когда дочерний процесс завершит отправку электронной почты и завершает работу, он закрывает соединение MySQL, которое закрывает соединение с родительскими процессами.
Если вы продолжаете идти по этому пути (и он преследуется с подобными тонкостями), вам нужно сделать что-то вроде
::ActiveRecord::Base.clear_all_connections!
Перед тем, как сделать вилку и
::ActiveRecord::Base.establish_connection
Далее. Вам придется делать аналогичную работу с такими услугами, как memcached или mongodb, если вы их используете.
Ответ 2
Будьте предельно осторожны при использовании вилки с рельсами/пассажиром, это может стать очень грязным! Вместо этого вы должны использовать resque или delayed_job для этой задачи!
Ответ 3
Вы можете восстановить соединение внутри вилки:
dbconfig = YAML::load(File.open('your_app_dir/config/database.yml'))
ActiveRecord::Base.establish_connection(dbconfig['development'])