Сколько соединений rails открывает в рекурсивной функции?

#ruby-on-rails

#ruby-on-rails

Вопрос:

У меня есть модель, которая имеет рекурсивную ссылку на саму себя, например, связанный список. Если я пишу функцию, подобную приведенной ниже (простите за мой синтаксис, Ruby — не мой любимый язык), чтобы следовать цепочке до конца. Предполагая, что это часть модели активной записи и next является внешним ключом к следующему узлу, что происходит за кулисами для этой функции? Сколько отдельных подключений к моей базе данных MySQL открывается активной записью и как долго они сохраняются?

 module LinkedList
  class Node < ActiveRecord::Base

    has_one :value
    has_one :next, foreign_key: 'id' class_name: 'Source::Incident'

    def fetch_all_nodes(current_node=nil, all_nodes=nil)

      current_node = current_node ? current_node : self
      all_nodes = all_nodes ? all_nodes : [self]

      if current_node.next
        all_nodes = fetch_all_nodes(current_node.next, all_nodes << current_node)

      all_nodes
   end
 end
end
  

Комментарии:

1. Можете ли вы также добавить свое базовое определение модели?

2. Немного уточнил — это должен быть простой гипотетический пример, поэтому, если потребуется больше деталей, пожалуйста, дайте мне знать!

Ответ №1:

Поскольку он написан как рекурсивная функция, у вас будет один SQL-вызов call на узел. Вызывается Next, получает связанные узлы и кэширует значение. (При необходимости вы можете перезагрузить его). Насколько я могу судить, эта реализация заканчивается одним объектом для каждой записи базы данных. Если бы вы в конечном итоге искали объект, который вы уже сохранили, это вызвало бы больше объектов и больше запросов к базе данных, но Rails имеет кэш запросов, так что это может сократить такие запросы.

Вы могли бы all_nodes вместо этого вернуть отложенный перечислитель, и тогда, если вы в конечном итоге не проверите весь хвост, у вас будет только один вызов на посещенный узел, и вы могли бы обрабатывать потенциально бесконечные (или даже циклические) списки.

Ответ №2:

ActiveRecord используется ActiveRecord::ConnectionAdapters::ConnectionPool для подключения к вашему хранилищу данных, пул которого по умолчанию состоит из 5 подключений. Таким образом, максимум, каждый экземпляр Rails / ActiveRecord будет использовать максимальное количество подключений к базе данных в качестве настроенного размера пула подключений.