класс ActiveRecord::ConnectionAdapters::ConnectionHandler
ConnectionHandler — это набор объектов ConnectionPool. Он используется для поддержания отдельных пулов соединений для моделей Active Record, которые подключаются к разным базам данных.
Например, предположим, что у вас есть 5 моделей с такой иерархией:
| +-- Book | | | +-- ScaryBook | +-- GoodBook +-- Author +-- BankAccount
Предположим, что модель Book должна подключаться к отдельной базе данных (то есть к базе данных, отличной от основной). Тогда Book, ScaryBook и GoodBook будут использовать один и тот же пул соединений. Аналогично, Author и BankAccount будут использовать один и тот же пул соединений. Однако, пул соединений, используемый Author/BankAccount, не тот же, что и используемый Book/ScaryBook/GoodBook.
Обычно существует только один экземпляр ConnectionHandler, доступный через ActiveRecord::Core.connection_handler. Модели Active Record используют его для определения пула соединений, который они должны использовать.
Публичные методы класса
# File activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb, line 483
def initialize
# These caches are keyed by klass.name, NOT klass. Keying them by klass
# alone would lead to memory leaks in development mode as all previous
# instances of the class would stay in memory.
@owner_to_pool = ThreadSafe::Cache.new(:initial_capacity => 2) do |h,k|
h[k] = ThreadSafe::Cache.new(:initial_capacity => 2)
end
@class_to_pool = ThreadSafe::Cache.new(:initial_capacity => 2) do |h,k|
h[k] = ThreadSafe::Cache.new
end
end Публичные методы экземпляра
Возвращает true, если среди пулов соединений, управляемых ConnectionHandler, есть активные соединения.
# File activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb, line 515 def active_connections? connection_pool_list.any?(&:active_connection?) end
Возвращает все используемые соединения текущей нити обратно в пул, а также возвращает соединения в кэше пула, связанные с нитями, которые больше не активны.
# File activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb, line 522 def clear_active_connections! connection_pool_list.each(&:release_connection) end
# File activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb, line 531 def clear_all_connections! connection_pool_list.each(&:disconnect!) end
Очищает кэш, который отображает классы.
# File activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb, line 527 def clear_reloadable_connections! connection_pool_list.each(&:clear_reloadable_connections!) end
Возвращает true, если для этого класса уже открыто доступное соединение.
# File activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb, line 546 def connected?(klass) conn = retrieve_connection_pool(klass) conn && conn.connected? end
# File activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb, line 495 def connection_pool_list owner_to_pool.values.compact end
# File activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb, line 499
def connection_pools
ActiveSupport::Deprecation.warn(
"In the next release, this will return the same as #connection_pool_list. " "(An array of pools, rather than a hash mapping specs to pools.)"
)
Hash[connection_pool_list.map { |pool| [pool.spec, pool] }]
end # File activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb, line 507 def establish_connection(owner, spec) @class_to_pool.clear raise RuntimeError, "Anonymous class is not allowed." unless owner.name owner_to_pool[owner.name] = ConnectionAdapters::ConnectionPool.new(spec) end
Удаляет соединение для данного класса. Это закроет активное соединение и определённое соединение (если они существуют). Результат может быть использован в качестве аргумента для #establish_connection для лёгкого повторного установления соединения.
# File activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb, line 555
def remove_connection(owner)
if pool = owner_to_pool.delete(owner.name)
@class_to_pool.clear
pool.automatic_reconnect = false
pool.disconnect!
pool.spec.config
end
end Извлечение пула соединений происходит часто, поэтому мы кэшируем его в @class_to_pool. Это делает извлечение пула соединений O(1) после разогрева процесса. При установлении или удалении соединения мы аннулируем кэш.
В идеале мы бы здесь использовали fetch, так как class_to_pool иногда может быть нулевым. Однако, бенчмаркинг (gist.github.com/jonleighton/3552829) показал, что fetch значительно медленнее, чем []. Поэтому в случае null, кэширование не произойдёт, но это нормально, так как случай null не является распространённым, для которого мы хотели бы оптимизировать.
# File activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb, line 573
def retrieve_connection_pool(klass)
class_to_pool[klass.name] ||= begin
until pool = pool_for(klass)
klass = klass.superclass
break unless klass <= Base
end
class_to_pool[klass.name] = pool
end
end
© 2004–2016 David Heinemeier Hansson
Licensed under the MIT License.