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 模型耦合,因为它不知道模型。模型需要向处理程序传递连接规范名称,以便查找正确的连接池。
- A
- C
- E
- F
- N
- R
类公共方法
new() 链接
来源: 显示 | 在 GitHub 上
# 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) 链接
如果 ConnectionHandler
管理的连接池中存在任何活动连接,则返回 true。
来源: 显示 | 在 GitHub 上
# 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
all_connection_pools() 链接
来源: 显示 | 在 GitHub 上
# 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) 链接
将当前线程正在使用的任何连接返回到池中,并将不再活动的线程缓存的连接也返回到池中。
来源: 显示 | 在 GitHub 上
# 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) 链接
来源: 显示 | 在 GitHub 上
# 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) 链接
清除映射类的缓存。
有关详细信息,请参阅 ConnectionPool#clear_reloadable_connections!
。
来源:显示 | 在 GitHub 上
# 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
connected?(connection_name, role: ActiveRecord::Base.current_role, shard: ActiveRecord::Base.current_shard) 链接
如果此类可访问的连接已打开,则返回 true。
来源:显示 | 在 GitHub 上
# 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
connection_pool_list(role = nil) 链接
返回连接处理程序和给定角色的池。如果传递了 :all
,则将返回属于连接处理程序的所有池。
来源:显示 | 在 GitHub 上
# 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
establish_connection(config, owner_name: Base, role: Base.current_role, shard: Base.current_shard, clobber: false) 链接
来源:显示 | 在 GitHub 上
# 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) 链接
断开所有当前空闲的连接。
有关详细信息,请参阅 ConnectionPool#flush!
。
来源:显示 | 在 GitHub 上
# 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
remove_connection_pool(connection_name, role: ActiveRecord::Base.current_role, shard: ActiveRecord::Base.current_shard) 链接
来源:显示 | 在 GitHub 上
# 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) 链接
检索连接池的操作非常频繁,因此我们将其缓存到 @connection_name_to_pool_manager 中。这使得在进程预热后检索连接池成为 O(1) 操作。当建立或移除连接时,我们会使缓存失效。
来源:显示 | 在 GitHub 上
# 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