класс ActiveRecord::ConnectionAdapters::ConnectionHandler
ConnectionHandler — это коллекция объектов ConnectionPool. Она используется для хранения отдельных пулов подключений, которые подключаются к различным базам данных.
Например, предположим, что у вас есть 5 моделей с такой иерархией:
class Author < ActiveRecord::Base end class BankAccount < ActiveRecord::Base end class Book < ActiveRecord::Base establish_connection "library_db" end class ScaryBook < Book end class GoodBook < Book end
И файл database.yml, который выглядит так:
development: database: my_application host: localhost library_db: database: library host: some.library.org
Ваша основная база данных в среде разработки — «my_application», но модель Book подключается к отдельной базе данных под названием «library_db» (эта база данных может находиться даже на другом компьютере).
Book, ScaryBook и GoodBook будут использовать один и тот же пул подключений к «library_db», а Author, BankAccount и любые другие созданные вами модели будут использовать стандартный пул подключений к «my_application».
Различные пулы подключений управляются единственным экземпляром ConnectionHandler, доступным через ActiveRecord::Core.connection_handler. Все модели Active Record используют этот обработчик для определения пула подключений, который они должны использовать.
Класс ConnectionHandler не связан с моделями Active, так как он не знает о модели. Модель должна передать имя спецификации обработчику, чтобы найти соответствующий пул подключений.
Публичные методы класса
# File activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb, line 836
def initialize
# These caches are keyed by spec.name (ConnectionSpecification#name).
@owner_to_pool = Concurrent::Map.new(:initial_capacity => 2) do |h,k|
h[k] = Concurrent::Map.new(:initial_capacity => 2)
end
end Публичные методы экземпляра
# File activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb, line 854 def active_connections? connection_pool_list.any?(&:active_connection?) end
Возвращает true, если среди пулов подключений, которые управляет ConnectionHandler, есть активные подключения.
# File activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb, line 861 def clear_active_connections! connection_pool_list.each(&:release_connection) end
Возвращает все используемые текущей нитью подключения обратно в пул, а также подключения, кэшированные нитями, которые больше не существуют.
# File activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb, line 872 def clear_all_connections! connection_pool_list.each(&:disconnect!) end
# File activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb, line 868 def clear_reloadable_connections! connection_pool_list.each(&:clear_reloadable_connections!) end
Очищает кэш, который отображает классы.
См. ActiveRecord::ConnectionAdapters::ConnectionPool#clear_reloadable_connections! для получения подробной информации.
# File activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb, line 890 def connected?(spec_name) conn = retrieve_connection_pool(spec_name) conn && conn.connected? end
Возвращает true, если для данного класса уже было открыто подключение.
# File activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb, line 843 def connection_pool_list owner_to_pool.values.compact end
# File activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb, line 848 def establish_connection(spec) owner_to_pool[spec.name] = ConnectionAdapters::ConnectionPool.new(spec) end
# File activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb, line 899
def remove_connection(spec_name)
if pool = owner_to_pool.delete(spec_name)
pool.automatic_reconnect = false
pool.disconnect!
pool.spec.config
end
end Удаляет подключение для данного класса. Это закроет активное подключение и определённое подключение (если они существуют). Результат может быть использован в качестве аргумента для #establish_connection для лёгкого повторного подключения.
# File activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb, line 916
def retrieve_connection_pool(spec_name)
owner_to_pool.fetch(spec_name) do
if ancestor_pool = pool_from_any_process_for(spec_name)
# A connection was established in an ancestor process that must have
# subsequently forked. We can't reuse the connection, but we can copy
# the specification and establish a new connection with it.
establish_connection(ancestor_pool.spec).tap do |pool|
pool.schema_cache = ancestor_pool.schema_cache if ancestor_pool.schema_cache
end
else
owner_to_pool[spec_name] = nil
end
end
end Извлечение пула подключений происходит очень часто, поэтому мы кэшируем его в @class_to_pool. Это делает извлечение пула подключений O(1) после прогрева процесса. Когда подключение устанавливается или удаляется, мы аннулируем кэш.
В идеале здесь мы бы использовали fetch, поскольку class_to_pool иногда может быть null. Однако, по результатам бенчмаркинга (gist.github.com/jonleighton/3552829) выяснилось, что fetch значительно медленнее, чем []. Поэтому в случае null кэширование не произойдёт, но это нормально, поскольку случай null не является распространённым, для которого мы хотели бы оптимизировать.
© 2004–2018 David Heinemeier Hansson
Licensed under the MIT License.