Spec-Zone.ru › Ruby on Rails 7.1

class ActiveRecord::ConnectionAdapters::ConnectionHandler

Parent:
Объект

Обработчик подключений Active Record

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::Base.connection_handler. Все модели Active Record используют этот обработчик для определения пула подключений, который они должны использовать.

Класс ConnectionHandler не связан с моделями Active, так как он не имеет информации о модели. Модели должны передать имя спецификации подключения обработчику, чтобы он мог найти правильный пул подключения.

Публичные методы класса

new() Показать исходный код
# File activerecord/lib/active_record/connection_adapters/abstract/connection_handler.rb, line 77
def initialize
  # These caches are keyed by pool_config.connection_name (PoolConfig#connection_name).
  @connection_name_to_pool_manager = Concurrent::Map.new(initial_capacity: 2)

  # Backup finalizer: if the forked child skipped Kernel#fork the early discard has not occurred
  ObjectSpace.define_finalizer self, FINALIZER
end

Публичные методы экземпляра

active_connections?(role = nil) Показать исходный код
# File activerecord/lib/active_record/connection_adapters/abstract/connection_handler.rb, line 173
def active_connections?(role = nil)
  if role.nil?
    deprecation_for_pool_handling(__method__)
    role = ActiveRecord::Base.current_role
  end

  each_connection_pool(role).any?(&:active_connection?)
end

Возвращает true, если среди пулов подключений, которыми управляет ConnectionHandler, существуют активные подключения.

all_connection_pools() Показать исходный код
# File activerecord/lib/active_record/connection_adapters/abstract/connection_handler.rb, line 97
      def all_connection_pools
        ActiveRecord.deprecator.warn(<<-MSG.squish)
          The `all_connection_pools` method is deprecated in favor of `connection_pool_list`.
          Call `connection_pool_list(:all)` to get the same behavior as `all_connection_pools`.
        MSG
        connection_name_to_pool_manager.values.flat_map { |m| m.pool_configs.map(&:pool) }
      end
clear_active_connections!(role = nil) Показать исходный код
# File activerecord/lib/active_record/connection_adapters/abstract/connection_handler.rb, line 185
def clear_active_connections!(role = nil)
  if role.nil?
    deprecation_for_pool_handling(__method__)
    role = ActiveRecord::Base.current_role
  end

  each_connection_pool(role).each(&:release_connection)
end

Возвращает все используемые текущей нитью подключения обратно в пул, а также возвращает подключения в пул, кэшированные нитями, которые больше не активны.

clear_all_connections!(role = nil) Показать исходный код
# File activerecord/lib/active_record/connection_adapters/abstract/connection_handler.rb, line 206
def clear_all_connections!(role = nil)
  if role.nil?
    deprecation_for_pool_handling(__method__)
    role = ActiveRecord::Base.current_role
  end

  each_connection_pool(role).each(&:disconnect!)
end
clear_reloadable_connections!(role = nil) Показать исходный код
# File activerecord/lib/active_record/connection_adapters/abstract/connection_handler.rb, line 197
def clear_reloadable_connections!(role = nil)
  if role.nil?
    deprecation_for_pool_handling(__method__)
    role = ActiveRecord::Base.current_role
  end

  each_connection_pool(role).each(&:clear_reloadable_connections!)
end

Очищает кэш, сопоставляющий классы.

См. ConnectionPool#clear_reloadable_connections! для получения подробной информации.

connected?(connection_name, role: ActiveRecord::Base.current_role, shard: ActiveRecord::Base.current_shard) Показать исходный код
# File activerecord/lib/active_record/connection_adapters/abstract/connection_handler.rb, line 251
def connected?(connection_name, role: ActiveRecord::Base.current_role, shard: ActiveRecord::Base.current_shard)
  pool = retrieve_connection_pool(connection_name, role: role, shard: shard)
  pool && pool.connected?
end

Возвращает true, если подключение, доступное для этого класса, уже открыто.

connection_pool_list(role = nil) Показать исходный код
# File activerecord/lib/active_record/connection_adapters/abstract/connection_handler.rb, line 107
def connection_pool_list(role = nil)
  if role.nil?
    deprecation_for_pool_handling(__method__)
    role = ActiveRecord::Base.current_role
    connection_name_to_pool_manager.values.flat_map { |m| m.pool_configs(role).map(&:pool) }
  elsif role == :all
    connection_name_to_pool_manager.values.flat_map { |m| m.pool_configs.map(&:pool) }
  else
    connection_name_to_pool_manager.values.flat_map { |m| m.pool_configs(role).map(&:pool) }
  end
end

Возвращает пулы для обработчика подключения и заданного роли. Если :all передано, будут возвращены все пулы, принадлежащие обработчику подключения.

Также является алиасом: connection_pools
connection_pools(role = nil)
Алиас для: connection_pool_list
establish_connection(config, owner_name: Base, role: Base.current_role, shard: Base.current_shard, clobber: false) Показать исходный код
# File activerecord/lib/active_record/connection_adapters/abstract/connection_handler.rb, line 131
def establish_connection(config, owner_name: Base, role: Base.current_role, shard: Base.current_shard, clobber: false)
  owner_name = determine_owner_name(owner_name, config)

  pool_config = resolve_pool_config(config, owner_name, role, shard)
  db_config = pool_config.db_config

  pool_manager = set_pool_manager(pool_config.connection_name)

  # If there is an existing pool with the same values as the pool_config
  # don't remove the connection. Connections should only be removed if we are
  # establishing a connection on a class that is already connected to a different
  # configuration.
  existing_pool_config = pool_manager.get_pool_config(role, shard)

  if !clobber && existing_pool_config && existing_pool_config.db_config == db_config
    # Update the pool_config's connection class if it differs. This is used
    # for ensuring that ActiveRecord::Base and the primary_abstract_class use
    # the same pool. Without this granular swapping will not work correctly.
    if owner_name.primary_class? && (existing_pool_config.connection_class != owner_name)
      existing_pool_config.connection_class = owner_name
    end

    existing_pool_config.pool
  else
    disconnect_pool_from_pool_manager(pool_manager, role, shard)
    pool_manager.set_pool_config(role, shard, pool_config)

    payload = {
      connection_name: pool_config.connection_name,
      role: role,
      shard: shard,
      config: db_config.configuration_hash
    }

    ActiveSupport::Notifications.instrumenter.instrument("!connection.active_record", payload) do
      pool_config.pool
    end
  end
end
flush_idle_connections!(role = nil) Показать исходный код
# File activerecord/lib/active_record/connection_adapters/abstract/connection_handler.rb, line 218
def flush_idle_connections!(role = nil)
  if role.nil?
    deprecation_for_pool_handling(__method__)
    role = ActiveRecord::Base.current_role
  end

  each_connection_pool(role).each(&:flush!)
end

Отключает все в настоящее время неактивные подключения.

См. ConnectionPool#flush! для получения подробной информации.

remove_connection_pool(connection_name, role: ActiveRecord::Base.current_role, shard: ActiveRecord::Base.current_shard) Показать исходный код
# File activerecord/lib/active_record/connection_adapters/abstract/connection_handler.rb, line 256
def remove_connection_pool(connection_name, role: ActiveRecord::Base.current_role, shard: ActiveRecord::Base.current_shard)
  if pool_manager = get_pool_manager(connection_name)
    disconnect_pool_from_pool_manager(pool_manager, role, shard)
  end
end
retrieve_connection_pool(connection_name, role: ActiveRecord::Base.current_role, shard: ActiveRecord::Base.current_shard) Показать исходный код
# File activerecord/lib/active_record/connection_adapters/abstract/connection_handler.rb, line 265
def retrieve_connection_pool(connection_name, role: ActiveRecord::Base.current_role, shard: ActiveRecord::Base.current_shard)
  pool_config = get_pool_manager(connection_name)&.get_pool_config(role, shard)
  pool_config&.pool
end

Извлечение пула подключений происходит часто, поэтому мы кэшируем его в @connection_name_to_pool_manager. Это делает извлечение пула подключения O(1) после разогрева процесса. При установлении или удалении подключения мы аннулируем кэш.

© 2004–2021 David Heinemeier Hansson
Licensed under the MIT License.

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API