ActiveRecord не может переподключиться при запуске внутри разветвленного / многопоточного приложения? - PullRequest
5 голосов
/ 29 марта 2011

Немного открытого вопроса, поэтому сначала я опишу проблему. У нас есть рабочий Resque , который должен вытолкнуть задания синхронизации данных из очереди, причины двоякие: использование Cron (и многократно оплачиваемое время загрузки среды Rails) и альтернативные очереди, хорошо, Github выдвинул против них довольно веские аргументы, когда они объявили Resque . Кроме того, функциональность временных рядов Redis уже играет большую роль в нашей инфраструктуре, где мы также перетасовываем данные TS в RRDTool и т. Д. *

Вот проблема , с обычными тремя часами между заданиями (но персонал может планировать задания в любое время… отсюда очередь), сервер PostgreSQL уходит. Достаточно легко вылечить, я ожидал, что установка reconnect: true в соответствующей среде гарантирует, что это сработает, как и ожидалось. Я прочитал в нескольких местах , которые reconnect: true не будут работать для приложений, которые используют fork(). Что, естественно, Resque делает, чтобы запустить своих рабочих ... Часть, которую я не понимаю, - это то, почему переподключение ActiveRecord не может работать в этих условиях?

Я заметил, что реализации reconnect! MySQL Adapter и PostgreSQL Adapter в ActiveRecord отличаются ... но в любом случае я ожидал, что конфигурация ActiveRecord reconnect: true будет работать.

Проблема кажется достаточно ясной, когда дочерний процесс существует, он закрывает файловые дескрипторы, созданные родителем (таким образом, разрывая соединение с базой данных) - возможно ли закрыть файловый дескриптор таким образом, что ActiveRecord не распознает, что соединение было разорвано?

Есть также, что стоит, вилка с поддержкой ActiveRecord () , которую я смог найти на Github, как тест - она ​​не проверена, но я предполагаю, что она работает (не пробовал с текущими рельсами ..)

У меня вопрос больше, Почему автоматическое переподключение в AR не может работать, если вы fork()? (и, в последнее время - я не могу быть единственным человеком, у которого возникла эта проблема; я я говорю об использовании PGSQL с Resque!)

1 Ответ

6 голосов
/ 18 апреля 2011

Хотя это не совсем ответ на вопрос «почему он не может переподключиться», но я думаю, что вам может помочь следующий код, помещенный где-то на этапе инициализации:


Resque.after_fork do |job|
  ActiveRecord::Base.connection.reconnect!
end

Обновление: относительноПереподключение - кажется, что это только функция MySQL.Вот как он используется в адаптере mysql: https://github.com/rails/rails/blob/master/activerecord/lib/active_record/connection_adapters/mysql_adapter.rb#L848 Как видите, он использует функцию переподключения основного драйвера.https://github.com/kwatch/mysql-ruby/blob/master/ext/mysql.c#L923

С другой стороны, адаптер postgresql ничего не делает в отношении опции reconnect, вы можете увидеть https://github.com/rails/rails/blob/master/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb

Кроме того, на сайте PostgreSQL явно сказаночто «Формирование процесса с открытым подключением libpq может привести к непредсказуемым результатам» - http://www.postgresql.org/docs/9.0/interactive/libpq-connect.html И также очевидно, что драйвер C не предоставляет никакой функции переподключения.

...