mirror of
https://github.com/rails/rails.git
synced 2022-11-09 12:12:34 -05:00
Rename the classes
This commit renames `RoleManager` -> `PoolManager` and `Role` -> `PoolConfig`. Once we introduced the previous commit, and looking at the existing code, it's clearer that `Role` and `RoleManager` are not the right names for these. Since this PR moves away from swapping the connection handler concepts around and the role concept will continue existing on the handler level, we need to rename this. A `PoolConfig` holds a `connection_specification_name` (we may rename this down the road), a `db_config`, a `schema_cache`, and a `pool`. It does feel like `pool` could eventually hold all of these things instead of having a `PoolConfig` object. This would remove one level of the object graph and reduce complexity. For now I'm leaving this object to keep the change churn low and will revisit later. Co-authored-by: John Crepezzi <seejohnrun@github.com>
This commit is contained in:
parent
a2a525bbb6
commit
6d81eab13d
16 changed files with 166 additions and 165 deletions
|
@ -9,8 +9,8 @@ module ActiveRecord
|
||||||
end
|
end
|
||||||
|
|
||||||
autoload :Column
|
autoload :Column
|
||||||
autoload :Role
|
autoload :PoolConfig
|
||||||
autoload :RoleManager
|
autoload :PoolManager
|
||||||
autoload :Resolver
|
autoload :Resolver
|
||||||
|
|
||||||
autoload_at "active_record/connection_adapters/abstract/schema_definitions" do
|
autoload_at "active_record/connection_adapters/abstract/schema_definitions" do
|
||||||
|
|
|
@ -370,21 +370,21 @@ module ActiveRecord
|
||||||
include ConnectionAdapters::AbstractPool
|
include ConnectionAdapters::AbstractPool
|
||||||
|
|
||||||
attr_accessor :automatic_reconnect, :checkout_timeout
|
attr_accessor :automatic_reconnect, :checkout_timeout
|
||||||
attr_reader :db_config, :size, :reaper, :role
|
attr_reader :db_config, :size, :reaper, :pool_config
|
||||||
|
|
||||||
delegate :schema_cache, :schema_cache=, to: :role
|
delegate :schema_cache, :schema_cache=, to: :pool_config
|
||||||
|
|
||||||
# Creates a new ConnectionPool object. +role+ is a Role
|
# Creates a new ConnectionPool object. +pool_config+ is a PoolConfig
|
||||||
# object which describes database connection information (e.g. adapter,
|
# object which describes database connection information (e.g. adapter,
|
||||||
# host name, username, password, etc), as well as the maximum size for
|
# host name, username, password, etc), as well as the maximum size for
|
||||||
# this ConnectionPool.
|
# this ConnectionPool.
|
||||||
#
|
#
|
||||||
# The default ConnectionPool maximum size is 5.
|
# The default ConnectionPool maximum size is 5.
|
||||||
def initialize(role)
|
def initialize(pool_config)
|
||||||
super()
|
super()
|
||||||
|
|
||||||
@role = role
|
@pool_config = pool_config
|
||||||
@db_config = role.db_config
|
@db_config = pool_config.db_config
|
||||||
|
|
||||||
@checkout_timeout = db_config.checkout_timeout
|
@checkout_timeout = db_config.checkout_timeout
|
||||||
@idle_timeout = db_config.idle_timeout
|
@idle_timeout = db_config.idle_timeout
|
||||||
|
@ -1003,8 +1003,8 @@ module ActiveRecord
|
||||||
private_constant :FINALIZER
|
private_constant :FINALIZER
|
||||||
|
|
||||||
def initialize
|
def initialize
|
||||||
# These caches are keyed by role.connection_specification_name (Role#connection_specification_name).
|
# These caches are keyed by pool_config.connection_specification_name (PoolConfig#connection_specification_name).
|
||||||
@owner_to_role_manager = Concurrent::Map.new(initial_capacity: 2)
|
@owner_to_pool_manager = Concurrent::Map.new(initial_capacity: 2)
|
||||||
|
|
||||||
# Backup finalizer: if the forked child skipped Kernel#fork the early discard has not occurred
|
# Backup finalizer: if the forked child skipped Kernel#fork the early discard has not occurred
|
||||||
ObjectSpace.define_finalizer self, FINALIZER
|
ObjectSpace.define_finalizer self, FINALIZER
|
||||||
|
@ -1031,36 +1031,36 @@ module ActiveRecord
|
||||||
end
|
end
|
||||||
|
|
||||||
def connection_pool_names # :nodoc:
|
def connection_pool_names # :nodoc:
|
||||||
owner_to_role_manager.keys
|
owner_to_pool_manager.keys
|
||||||
end
|
end
|
||||||
|
|
||||||
def connection_pool_list
|
def connection_pool_list
|
||||||
owner_to_role_manager.values.compact.flat_map { |rc| rc.roles.map(&:pool) }
|
owner_to_pool_manager.values.compact.flat_map { |m| m.pool_configs.map(&:pool) }
|
||||||
end
|
end
|
||||||
alias :connection_pools :connection_pool_list
|
alias :connection_pools :connection_pool_list
|
||||||
|
|
||||||
def establish_connection(config, role_name = :default)
|
def establish_connection(config, pool_key = :default)
|
||||||
resolver = Resolver.new(Base.configurations)
|
resolver = Resolver.new(Base.configurations)
|
||||||
role = resolver.resolve_role(config)
|
pool_config = resolver.resolve_pool_config(config)
|
||||||
db_config = role.db_config
|
db_config = pool_config.db_config
|
||||||
|
|
||||||
remove_connection(role.connection_specification_name, role_name)
|
remove_connection(pool_config.connection_specification_name, pool_key)
|
||||||
|
|
||||||
message_bus = ActiveSupport::Notifications.instrumenter
|
message_bus = ActiveSupport::Notifications.instrumenter
|
||||||
payload = {
|
payload = {
|
||||||
connection_id: object_id
|
connection_id: object_id
|
||||||
}
|
}
|
||||||
if role
|
if pool_config
|
||||||
payload[:spec_name] = role.connection_specification_name
|
payload[:spec_name] = pool_config.connection_specification_name
|
||||||
payload[:config] = db_config.configuration_hash
|
payload[:config] = db_config.configuration_hash
|
||||||
end
|
end
|
||||||
|
|
||||||
owner_to_role_manager[role.connection_specification_name] ||= RoleManager.new
|
owner_to_pool_manager[pool_config.connection_specification_name] ||= PoolManager.new
|
||||||
role_manager = owner_to_role_manager[role.connection_specification_name]
|
pool_manager = owner_to_pool_manager[pool_config.connection_specification_name]
|
||||||
role_manager.set_role(role_name, role)
|
pool_manager.set_pool_config(pool_key, pool_config)
|
||||||
|
|
||||||
message_bus.instrument("!connection.active_record", payload) do
|
message_bus.instrument("!connection.active_record", payload) do
|
||||||
role.pool
|
pool_config.pool
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -1116,8 +1116,8 @@ module ActiveRecord
|
||||||
|
|
||||||
# Returns true if a connection that's accessible to this class has
|
# Returns true if a connection that's accessible to this class has
|
||||||
# already been opened.
|
# already been opened.
|
||||||
def connected?(spec_name, role_name = :default)
|
def connected?(spec_name, pool_key = :default)
|
||||||
pool = retrieve_connection_pool(spec_name, role_name)
|
pool = retrieve_connection_pool(spec_name, pool_key)
|
||||||
pool && pool.connected?
|
pool && pool.connected?
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -1125,27 +1125,27 @@ module ActiveRecord
|
||||||
# connection and the defined connection (if they exist). The result
|
# connection and the defined connection (if they exist). The result
|
||||||
# can be used as an argument for #establish_connection, for easily
|
# can be used as an argument for #establish_connection, for easily
|
||||||
# re-establishing the connection.
|
# re-establishing the connection.
|
||||||
def remove_connection(spec_name, role_name = :default)
|
def remove_connection(spec_name, pool_key = :default)
|
||||||
if role_manager = owner_to_role_manager[spec_name]
|
if pool_manager = owner_to_pool_manager[spec_name]
|
||||||
role = role_manager.remove_role(role_name)
|
pool_config = pool_manager.remove_pool_config(pool_key)
|
||||||
|
|
||||||
if role
|
if pool_config
|
||||||
role.disconnect!
|
pool_config.disconnect!
|
||||||
role.db_config.configuration_hash
|
pool_config.db_config.configuration_hash
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# Retrieving the connection pool happens a lot, so we cache it in @owner_to_role_manager.
|
# Retrieving the connection pool happens a lot, so we cache it in @owner_to_pool_manager.
|
||||||
# This makes retrieving the connection pool O(1) once the process is warm.
|
# This makes retrieving the connection pool O(1) once the process is warm.
|
||||||
# When a connection is established or removed, we invalidate the cache.
|
# When a connection is established or removed, we invalidate the cache.
|
||||||
def retrieve_connection_pool(spec_name, role_name = :default)
|
def retrieve_connection_pool(spec_name, pool_key = :default)
|
||||||
role = owner_to_role_manager[spec_name]&.get_role(role_name)
|
pool_config = owner_to_pool_manager[spec_name]&.get_pool_config(pool_key)
|
||||||
role&.pool
|
pool_config&.pool
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
attr_reader :owner_to_role_manager
|
attr_reader :owner_to_pool_manager
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
module ActiveRecord
|
module ActiveRecord
|
||||||
module ConnectionAdapters
|
module ConnectionAdapters
|
||||||
class Role # :nodoc:
|
class PoolConfig # :nodoc:
|
||||||
include Mutex_m
|
include Mutex_m
|
||||||
|
|
||||||
attr_reader :db_config, :connection_specification_name
|
attr_reader :db_config, :connection_specification_name
|
||||||
|
@ -60,4 +60,4 @@ module ActiveRecord
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
ActiveSupport::ForkTracker.after_fork { ActiveRecord::ConnectionAdapters::Role.discard_pools! }
|
ActiveSupport::ForkTracker.after_fork { ActiveRecord::ConnectionAdapters::PoolConfig.discard_pools! }
|
|
@ -0,0 +1,27 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module ActiveRecord
|
||||||
|
module ConnectionAdapters
|
||||||
|
class PoolManager # :nodoc:
|
||||||
|
def initialize
|
||||||
|
@name_to_pool_config = {}
|
||||||
|
end
|
||||||
|
|
||||||
|
def pool_configs
|
||||||
|
@name_to_pool_config.values
|
||||||
|
end
|
||||||
|
|
||||||
|
def remove_pool_config(key)
|
||||||
|
@name_to_pool_config.delete(key)
|
||||||
|
end
|
||||||
|
|
||||||
|
def get_pool_config(key)
|
||||||
|
@name_to_pool_config[key]
|
||||||
|
end
|
||||||
|
|
||||||
|
def set_pool_config(key, pool_config)
|
||||||
|
@name_to_pool_config[key] = pool_config
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
module ActiveRecord
|
module ActiveRecord
|
||||||
module ConnectionAdapters
|
module ConnectionAdapters
|
||||||
# Builds a Role from user input.
|
# Builds a PoolConfig from user input.
|
||||||
class Resolver # :nodoc:
|
class Resolver # :nodoc:
|
||||||
attr_reader :configurations
|
attr_reader :configurations
|
||||||
|
|
||||||
|
@ -11,17 +11,17 @@ module ActiveRecord
|
||||||
@configurations = configurations
|
@configurations = configurations
|
||||||
end
|
end
|
||||||
|
|
||||||
# Returns an instance of Role for a given adapter.
|
# Returns an instance of PoolConfig for a given adapter.
|
||||||
# Accepts a hash one layer deep that contains all connection information.
|
# Accepts a hash one layer deep that contains all connection information.
|
||||||
#
|
#
|
||||||
# == Example
|
# == Example
|
||||||
#
|
#
|
||||||
# config = { "production" => { "host" => "localhost", "database" => "foo", "adapter" => "sqlite3" } }
|
# config = { "production" => { "host" => "localhost", "database" => "foo", "adapter" => "sqlite3" } }
|
||||||
# role = Resolver.new(config).resolve_role(:production)
|
# pool_config = Resolver.new(config).resolve_pool_config(:production)
|
||||||
# role.db_config.configuration_hash
|
# pool_config.db_config.configuration_hash
|
||||||
# # => { host: "localhost", database: "foo", adapter: "sqlite3" }
|
# # => { host: "localhost", database: "foo", adapter: "sqlite3" }
|
||||||
#
|
#
|
||||||
def resolve_role(config)
|
def resolve_pool_config(config)
|
||||||
pool_name = config if config.is_a?(Symbol)
|
pool_name = config if config.is_a?(Symbol)
|
||||||
|
|
||||||
db_config = resolve(config, pool_name)
|
db_config = resolve(config, pool_name)
|
||||||
|
@ -53,7 +53,7 @@ module ActiveRecord
|
||||||
raise AdapterNotFound, "database configuration specifies nonexistent #{db_config.adapter} adapter"
|
raise AdapterNotFound, "database configuration specifies nonexistent #{db_config.adapter} adapter"
|
||||||
end
|
end
|
||||||
|
|
||||||
Role.new(db_config.configuration_hash.delete(:name) || "primary", db_config)
|
PoolConfig.new(db_config.configuration_hash.delete(:name) || "primary", db_config)
|
||||||
end
|
end
|
||||||
|
|
||||||
# Returns fully resolved connection, accepts hash, string or symbol.
|
# Returns fully resolved connection, accepts hash, string or symbol.
|
||||||
|
|
|
@ -1,27 +0,0 @@
|
||||||
# frozen_string_literal: true
|
|
||||||
|
|
||||||
module ActiveRecord
|
|
||||||
module ConnectionAdapters
|
|
||||||
class RoleManager # :nodoc:
|
|
||||||
def initialize
|
|
||||||
@name_to_role = {}
|
|
||||||
end
|
|
||||||
|
|
||||||
def roles
|
|
||||||
@name_to_role.values
|
|
||||||
end
|
|
||||||
|
|
||||||
def remove_role(name)
|
|
||||||
@name_to_role.delete(name)
|
|
||||||
end
|
|
||||||
|
|
||||||
def get_role(name)
|
|
||||||
@name_to_role[name]
|
|
||||||
end
|
|
||||||
|
|
||||||
def set_role(name, role)
|
|
||||||
@name_to_role[name] = role
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -192,11 +192,11 @@ module ActiveRecord
|
||||||
ActiveRecord::Base.connection_handlers.values.each do |handler|
|
ActiveRecord::Base.connection_handlers.values.each do |handler|
|
||||||
if handler != writing_handler
|
if handler != writing_handler
|
||||||
handler.connection_pool_names.each do |name|
|
handler.connection_pool_names.each do |name|
|
||||||
writing_role_manager = writing_handler.send(:owner_to_role_manager)[name]
|
writing_pool_manager = writing_handler.send(:owner_to_pool_manager)[name]
|
||||||
writing_role = writing_role_manager.get_role(:default)
|
writing_pool_config = writing_pool_manager.get_pool_config(:default)
|
||||||
|
|
||||||
role_manager = handler.send(:owner_to_role_manager)[name]
|
pool_manager = handler.send(:owner_to_pool_manager)[name]
|
||||||
role_manager.set_role(:default, writing_role)
|
pool_manager.set_pool_config(:default, writing_pool_config)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -40,8 +40,8 @@ module ActiveRecord
|
||||||
|
|
||||||
def test_close
|
def test_close
|
||||||
db_config = ActiveRecord::DatabaseConfigurations::HashConfig.new("test", "primary", {})
|
db_config = ActiveRecord::DatabaseConfigurations::HashConfig.new("test", "primary", {})
|
||||||
role = ActiveRecord::ConnectionAdapters::Role.new("primary", db_config)
|
pool_config = ActiveRecord::ConnectionAdapters::PoolConfig.new("primary", db_config)
|
||||||
pool = Pool.new(role)
|
pool = Pool.new(pool_config)
|
||||||
pool.insert_connection_for_test! @adapter
|
pool.insert_connection_for_test! @adapter
|
||||||
@adapter.pool = pool
|
@adapter.pool = pool
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@ require "models/person"
|
||||||
|
|
||||||
module ActiveRecord
|
module ActiveRecord
|
||||||
module ConnectionAdapters
|
module ConnectionAdapters
|
||||||
class ConnectionHandlersMultiRoleTest < ActiveRecord::TestCase
|
class ConnectionHandlersMultiPoolConfigTest < ActiveRecord::TestCase
|
||||||
self.use_transactional_tests = false
|
self.use_transactional_tests = false
|
||||||
|
|
||||||
fixtures :people
|
fixtures :people
|
||||||
|
@ -22,7 +22,7 @@ module ActiveRecord
|
||||||
end
|
end
|
||||||
|
|
||||||
unless in_memory_db?
|
unless in_memory_db?
|
||||||
def test_establish_connection_with_roles
|
def test_establish_connection_with_pool_configs
|
||||||
previous_env, ENV["RAILS_ENV"] = ENV["RAILS_ENV"], "default_env"
|
previous_env, ENV["RAILS_ENV"] = ENV["RAILS_ENV"], "default_env"
|
||||||
|
|
||||||
config = {
|
config = {
|
||||||
|
@ -34,10 +34,10 @@ module ActiveRecord
|
||||||
@prev_configs, ActiveRecord::Base.configurations = ActiveRecord::Base.configurations, config
|
@prev_configs, ActiveRecord::Base.configurations = ActiveRecord::Base.configurations, config
|
||||||
|
|
||||||
@writing_handler.establish_connection(:primary)
|
@writing_handler.establish_connection(:primary)
|
||||||
@writing_handler.establish_connection(:primary, :role_two)
|
@writing_handler.establish_connection(:primary, :pool_config_two)
|
||||||
|
|
||||||
default_pool = @writing_handler.retrieve_connection_pool("primary", :default)
|
default_pool = @writing_handler.retrieve_connection_pool("primary", :default)
|
||||||
other_pool = @writing_handler.retrieve_connection_pool("primary", :role_two)
|
other_pool = @writing_handler.retrieve_connection_pool("primary", :pool_config_two)
|
||||||
|
|
||||||
assert_not_nil default_pool
|
assert_not_nil default_pool
|
||||||
assert_not_equal default_pool, other_pool
|
assert_not_equal default_pool, other_pool
|
||||||
|
@ -62,13 +62,13 @@ module ActiveRecord
|
||||||
@prev_configs, ActiveRecord::Base.configurations = ActiveRecord::Base.configurations, config
|
@prev_configs, ActiveRecord::Base.configurations = ActiveRecord::Base.configurations, config
|
||||||
|
|
||||||
@writing_handler.establish_connection(:primary)
|
@writing_handler.establish_connection(:primary)
|
||||||
@writing_handler.establish_connection(:primary, :role_two)
|
@writing_handler.establish_connection(:primary, :pool_config_two)
|
||||||
|
|
||||||
# remove default
|
# remove default
|
||||||
@writing_handler.remove_connection("primary")
|
@writing_handler.remove_connection("primary")
|
||||||
|
|
||||||
assert_nil @writing_handler.retrieve_connection_pool("primary")
|
assert_nil @writing_handler.retrieve_connection_pool("primary")
|
||||||
assert_not_nil @writing_handler.retrieve_connection_pool("primary", :role_two)
|
assert_not_nil @writing_handler.retrieve_connection_pool("primary", :pool_config_two)
|
||||||
ensure
|
ensure
|
||||||
ActiveRecord::Base.configurations = @prev_configs
|
ActiveRecord::Base.configurations = @prev_configs
|
||||||
ActiveRecord::Base.establish_connection(:arunit)
|
ActiveRecord::Base.establish_connection(:arunit)
|
||||||
|
@ -87,18 +87,19 @@ module ActiveRecord
|
||||||
@prev_configs, ActiveRecord::Base.configurations = ActiveRecord::Base.configurations, config
|
@prev_configs, ActiveRecord::Base.configurations = ActiveRecord::Base.configurations, config
|
||||||
|
|
||||||
@writing_handler.establish_connection(:primary)
|
@writing_handler.establish_connection(:primary)
|
||||||
@writing_handler.establish_connection(:primary, :role_two)
|
@writing_handler.establish_connection(:primary, :pool_config_two)
|
||||||
|
|
||||||
# connect to default
|
# connect to default
|
||||||
@writing_handler.connection_pool_list.first.checkout
|
@writing_handler.connection_pool_list.first.checkout
|
||||||
|
|
||||||
assert @writing_handler.connected?("primary")
|
assert @writing_handler.connected?("primary")
|
||||||
assert @writing_handler.connected?("primary", :default)
|
assert @writing_handler.connected?("primary", :default)
|
||||||
assert_not @writing_handler.connected?("primary", :role_two)
|
assert_not @writing_handler.connected?("primary", :pool_config_two)
|
||||||
ensure
|
ensure
|
||||||
ActiveRecord::Base.configurations = @prev_configs
|
ActiveRecord::Base.configurations = @prev_configs
|
||||||
ActiveRecord::Base.establish_connection(:arunit)
|
ActiveRecord::Base.establish_connection(:arunit)
|
||||||
ENV["RAILS_ENV"] = previous_env
|
ENV["RAILS_ENV"] = previous_env
|
||||||
|
FileUtils.rm_rf "db"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
|
@ -13,8 +13,8 @@ module ActiveRecord
|
||||||
|
|
||||||
# Keep a duplicate pool so we do not bother others
|
# Keep a duplicate pool so we do not bother others
|
||||||
@db_config = ActiveRecord::Base.connection_pool.db_config
|
@db_config = ActiveRecord::Base.connection_pool.db_config
|
||||||
@role = ActiveRecord::ConnectionAdapters::Role.new("primary", @db_config)
|
@pool_config = ActiveRecord::ConnectionAdapters::PoolConfig.new("primary", @db_config)
|
||||||
@pool = ConnectionPool.new(@role)
|
@pool = ConnectionPool.new(@pool_config)
|
||||||
|
|
||||||
if in_memory_db?
|
if in_memory_db?
|
||||||
# Separate connections to an in-memory database create an entirely new database,
|
# Separate connections to an in-memory database create an entirely new database,
|
||||||
|
@ -201,8 +201,8 @@ module ActiveRecord
|
||||||
def test_idle_timeout_configuration
|
def test_idle_timeout_configuration
|
||||||
@pool.disconnect!
|
@pool.disconnect!
|
||||||
@db_config.configuration_hash.merge!(idle_timeout: "0.02")
|
@db_config.configuration_hash.merge!(idle_timeout: "0.02")
|
||||||
role = ActiveRecord::ConnectionAdapters::Role.new("primary", @db_config)
|
pool_config = ActiveRecord::ConnectionAdapters::PoolConfig.new("primary", @db_config)
|
||||||
@pool = ConnectionPool.new(role)
|
@pool = ConnectionPool.new(pool_config)
|
||||||
idle_conn = @pool.checkout
|
idle_conn = @pool.checkout
|
||||||
@pool.checkin(idle_conn)
|
@pool.checkin(idle_conn)
|
||||||
|
|
||||||
|
@ -226,8 +226,8 @@ module ActiveRecord
|
||||||
def test_disable_flush
|
def test_disable_flush
|
||||||
@pool.disconnect!
|
@pool.disconnect!
|
||||||
@db_config.configuration_hash.merge!(idle_timeout: -5)
|
@db_config.configuration_hash.merge!(idle_timeout: -5)
|
||||||
role = ActiveRecord::ConnectionAdapters::Role.new("primary", @db_config)
|
pool_config = ActiveRecord::ConnectionAdapters::PoolConfig.new("primary", @db_config)
|
||||||
@pool = ConnectionPool.new(role)
|
@pool = ConnectionPool.new(pool_config)
|
||||||
idle_conn = @pool.checkout
|
idle_conn = @pool.checkout
|
||||||
@pool.checkin(idle_conn)
|
@pool.checkin(idle_conn)
|
||||||
|
|
||||||
|
@ -317,7 +317,7 @@ module ActiveRecord
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_checkout_behaviour
|
def test_checkout_behaviour
|
||||||
pool = ConnectionPool.new(@role)
|
pool = ConnectionPool.new(@pool_config)
|
||||||
main_connection = pool.connection
|
main_connection = pool.connection
|
||||||
assert_not_nil main_connection
|
assert_not_nil main_connection
|
||||||
threads = []
|
threads = []
|
||||||
|
@ -450,7 +450,7 @@ module ActiveRecord
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_automatic_reconnect_restores_after_disconnect
|
def test_automatic_reconnect_restores_after_disconnect
|
||||||
pool = ConnectionPool.new(@role)
|
pool = ConnectionPool.new(@pool_config)
|
||||||
assert pool.automatic_reconnect
|
assert pool.automatic_reconnect
|
||||||
assert pool.connection
|
assert pool.connection
|
||||||
|
|
||||||
|
@ -459,7 +459,7 @@ module ActiveRecord
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_automatic_reconnect_can_be_disabled
|
def test_automatic_reconnect_can_be_disabled
|
||||||
pool = ConnectionPool.new(@role)
|
pool = ConnectionPool.new(@pool_config)
|
||||||
pool.disconnect!
|
pool.disconnect!
|
||||||
pool.automatic_reconnect = false
|
pool.automatic_reconnect = false
|
||||||
|
|
||||||
|
@ -723,10 +723,10 @@ module ActiveRecord
|
||||||
old_config = @db_config.configuration_hash
|
old_config = @db_config.configuration_hash
|
||||||
db_config = ActiveRecord::DatabaseConfigurations::HashConfig.new("arunit", "primary", old_config.dup)
|
db_config = ActiveRecord::DatabaseConfigurations::HashConfig.new("arunit", "primary", old_config.dup)
|
||||||
|
|
||||||
db_config.configuration_hash[:pool] = 1 # this is safe to do, because .dupped Role also auto-dups its config
|
db_config.configuration_hash[:pool] = 1 # this is safe to do, because .dupped PoolConfig also auto-dups its config
|
||||||
|
|
||||||
role = ActiveRecord::ConnectionAdapters::Role.new("primary", db_config)
|
pool_config = ActiveRecord::ConnectionAdapters::PoolConfig.new("primary", db_config)
|
||||||
yield(pool = ConnectionPool.new(role))
|
yield(pool = ConnectionPool.new(pool_config))
|
||||||
ensure
|
ensure
|
||||||
pool.disconnect! if pool
|
pool.disconnect! if pool
|
||||||
end
|
end
|
||||||
|
|
|
@ -14,8 +14,8 @@ class TestDisconnectedAdapter < ActiveRecord::TestCase
|
||||||
|
|
||||||
teardown do
|
teardown do
|
||||||
return if in_memory_db?
|
return if in_memory_db?
|
||||||
role = ActiveRecord::Base.connection_config
|
config = ActiveRecord::Base.connection_config
|
||||||
ActiveRecord::Base.establish_connection(role)
|
ActiveRecord::Base.establish_connection(config)
|
||||||
end
|
end
|
||||||
|
|
||||||
unless in_memory_db?
|
unless in_memory_db?
|
||||||
|
|
|
@ -1414,10 +1414,10 @@ class MultipleDatabaseFixturesTest < ActiveRecord::TestCase
|
||||||
|
|
||||||
private
|
private
|
||||||
def with_temporary_connection_pool
|
def with_temporary_connection_pool
|
||||||
role = ActiveRecord::Base.connection_handler.send(:owner_to_role_manager).fetch("primary").get_role(:default)
|
pool_config = ActiveRecord::Base.connection_handler.send(:owner_to_pool_manager).fetch("primary").get_pool_config(:default)
|
||||||
new_pool = ActiveRecord::ConnectionAdapters::ConnectionPool.new(role)
|
new_pool = ActiveRecord::ConnectionAdapters::ConnectionPool.new(pool_config)
|
||||||
|
|
||||||
role.stub(:pool, new_pool) do
|
pool_config.stub(:pool, new_pool) do
|
||||||
yield
|
yield
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -4,23 +4,23 @@ require "cases/helper"
|
||||||
|
|
||||||
module ActiveRecord
|
module ActiveRecord
|
||||||
module ConnectionAdapters
|
module ConnectionAdapters
|
||||||
class Role
|
class PoolConfig
|
||||||
class ResolverTest < ActiveRecord::TestCase
|
class ResolverTest < ActiveRecord::TestCase
|
||||||
def resolve(role, config = {})
|
def resolve(pool_config, config = {})
|
||||||
configs = ActiveRecord::DatabaseConfigurations.new(config)
|
configs = ActiveRecord::DatabaseConfigurations.new(config)
|
||||||
resolver = ConnectionAdapters::Resolver.new(configs)
|
resolver = ConnectionAdapters::Resolver.new(configs)
|
||||||
resolver.resolve(role, role).configuration_hash
|
resolver.resolve(pool_config, pool_config).configuration_hash
|
||||||
end
|
end
|
||||||
|
|
||||||
def resolve_role(role, config = {})
|
def resolve_pool_config(pool_config, config = {})
|
||||||
configs = ActiveRecord::DatabaseConfigurations.new(config)
|
configs = ActiveRecord::DatabaseConfigurations.new(config)
|
||||||
resolver = ConnectionAdapters::Resolver.new(configs)
|
resolver = ConnectionAdapters::Resolver.new(configs)
|
||||||
resolver.resolve_role(role)
|
resolver.resolve_pool_config(pool_config)
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_url_invalid_adapter
|
def test_url_invalid_adapter
|
||||||
error = assert_raises(LoadError) do
|
error = assert_raises(LoadError) do
|
||||||
resolve_role "ridiculous://foo?encoding=utf8"
|
resolve_pool_config "ridiculous://foo?encoding=utf8"
|
||||||
end
|
end
|
||||||
|
|
||||||
assert_match "Could not load the 'ridiculous' Active Record adapter. Ensure that the adapter is spelled correctly in config/database.yml and that you've added the necessary adapter gem to your Gemfile.", error.message
|
assert_match "Could not load the 'ridiculous' Active Record adapter. Ensure that the adapter is spelled correctly in config/database.yml and that you've added the necessary adapter gem to your Gemfile.", error.message
|
||||||
|
@ -28,7 +28,7 @@ module ActiveRecord
|
||||||
|
|
||||||
def test_error_if_no_adapter_method
|
def test_error_if_no_adapter_method
|
||||||
error = assert_raises(AdapterNotFound) do
|
error = assert_raises(AdapterNotFound) do
|
||||||
resolve_role "abstract://foo?encoding=utf8"
|
resolve_pool_config "abstract://foo?encoding=utf8"
|
||||||
end
|
end
|
||||||
|
|
||||||
assert_match "database configuration specifies nonexistent abstract adapter", error.message
|
assert_match "database configuration specifies nonexistent abstract adapter", error.message
|
||||||
|
@ -38,121 +38,121 @@ module ActiveRecord
|
||||||
# checks that the adapter file can be required in.
|
# checks that the adapter file can be required in.
|
||||||
|
|
||||||
def test_url_from_environment
|
def test_url_from_environment
|
||||||
role = resolve :production, "production" => "abstract://foo?encoding=utf8"
|
pool_config = resolve :production, "production" => "abstract://foo?encoding=utf8"
|
||||||
assert_equal({
|
assert_equal({
|
||||||
adapter: "abstract",
|
adapter: "abstract",
|
||||||
host: "foo",
|
host: "foo",
|
||||||
encoding: "utf8",
|
encoding: "utf8",
|
||||||
name: "production"
|
name: "production"
|
||||||
}, role)
|
}, pool_config)
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_url_sub_key
|
def test_url_sub_key
|
||||||
role = resolve :production, "production" => { "url" => "abstract://foo?encoding=utf8" }
|
pool_config = resolve :production, "production" => { "url" => "abstract://foo?encoding=utf8" }
|
||||||
assert_equal({
|
assert_equal({
|
||||||
adapter: "abstract",
|
adapter: "abstract",
|
||||||
host: "foo",
|
host: "foo",
|
||||||
encoding: "utf8",
|
encoding: "utf8",
|
||||||
name: "production"
|
name: "production"
|
||||||
}, role)
|
}, pool_config)
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_url_sub_key_merges_correctly
|
def test_url_sub_key_merges_correctly
|
||||||
hash = { "url" => "abstract://foo?encoding=utf8&", "adapter" => "sqlite3", "host" => "bar", "pool" => "3" }
|
hash = { "url" => "abstract://foo?encoding=utf8&", "adapter" => "sqlite3", "host" => "bar", "pool" => "3" }
|
||||||
role = resolve :production, "production" => hash
|
pool_config = resolve :production, "production" => hash
|
||||||
assert_equal({
|
assert_equal({
|
||||||
adapter: "abstract",
|
adapter: "abstract",
|
||||||
host: "foo",
|
host: "foo",
|
||||||
encoding: "utf8",
|
encoding: "utf8",
|
||||||
pool: "3",
|
pool: "3",
|
||||||
name: "production"
|
name: "production"
|
||||||
}, role)
|
}, pool_config)
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_url_host_no_db
|
def test_url_host_no_db
|
||||||
role = resolve "abstract://foo?encoding=utf8"
|
pool_config = resolve "abstract://foo?encoding=utf8"
|
||||||
assert_equal({
|
assert_equal({
|
||||||
adapter: "abstract",
|
adapter: "abstract",
|
||||||
host: "foo",
|
host: "foo",
|
||||||
encoding: "utf8"
|
encoding: "utf8"
|
||||||
}, role)
|
}, pool_config)
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_url_missing_scheme
|
def test_url_missing_scheme
|
||||||
role = resolve "foo"
|
pool_config = resolve "foo"
|
||||||
assert_equal({ database: "foo" }, role)
|
assert_equal({ database: "foo" }, pool_config)
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_url_host_db
|
def test_url_host_db
|
||||||
role = resolve "abstract://foo/bar?encoding=utf8"
|
pool_config = resolve "abstract://foo/bar?encoding=utf8"
|
||||||
assert_equal({
|
assert_equal({
|
||||||
adapter: "abstract",
|
adapter: "abstract",
|
||||||
database: "bar",
|
database: "bar",
|
||||||
host: "foo",
|
host: "foo",
|
||||||
encoding: "utf8"
|
encoding: "utf8"
|
||||||
}, role)
|
}, pool_config)
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_url_port
|
def test_url_port
|
||||||
role = resolve "abstract://foo:123?encoding=utf8"
|
pool_config = resolve "abstract://foo:123?encoding=utf8"
|
||||||
assert_equal({
|
assert_equal({
|
||||||
adapter: "abstract",
|
adapter: "abstract",
|
||||||
port: 123,
|
port: 123,
|
||||||
host: "foo",
|
host: "foo",
|
||||||
encoding: "utf8"
|
encoding: "utf8"
|
||||||
}, role)
|
}, pool_config)
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_encoded_password
|
def test_encoded_password
|
||||||
password = "am@z1ng_p@ssw0rd#!"
|
password = "am@z1ng_p@ssw0rd#!"
|
||||||
encoded_password = URI.encode_www_form_component(password)
|
encoded_password = URI.encode_www_form_component(password)
|
||||||
role = resolve "abstract://foo:#{encoded_password}@localhost/bar"
|
pool_config = resolve "abstract://foo:#{encoded_password}@localhost/bar"
|
||||||
assert_equal password, role[:password]
|
assert_equal password, pool_config[:password]
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_url_with_authority_for_sqlite3
|
def test_url_with_authority_for_sqlite3
|
||||||
role = resolve "sqlite3:///foo_test"
|
pool_config = resolve "sqlite3:///foo_test"
|
||||||
assert_equal("/foo_test", role[:database])
|
assert_equal("/foo_test", pool_config[:database])
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_url_absolute_path_for_sqlite3
|
def test_url_absolute_path_for_sqlite3
|
||||||
role = resolve "sqlite3:/foo_test"
|
pool_config = resolve "sqlite3:/foo_test"
|
||||||
assert_equal("/foo_test", role[:database])
|
assert_equal("/foo_test", pool_config[:database])
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_url_relative_path_for_sqlite3
|
def test_url_relative_path_for_sqlite3
|
||||||
role = resolve "sqlite3:foo_test"
|
pool_config = resolve "sqlite3:foo_test"
|
||||||
assert_equal("foo_test", role[:database])
|
assert_equal("foo_test", pool_config[:database])
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_url_memory_db_for_sqlite3
|
def test_url_memory_db_for_sqlite3
|
||||||
role = resolve "sqlite3::memory:"
|
pool_config = resolve "sqlite3::memory:"
|
||||||
assert_equal(":memory:", role[:database])
|
assert_equal(":memory:", pool_config[:database])
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_url_sub_key_for_sqlite3
|
def test_url_sub_key_for_sqlite3
|
||||||
role = resolve :production, "production" => { "url" => "sqlite3:foo?encoding=utf8" }
|
pool_config = resolve :production, "production" => { "url" => "sqlite3:foo?encoding=utf8" }
|
||||||
assert_equal({
|
assert_equal({
|
||||||
adapter: "sqlite3",
|
adapter: "sqlite3",
|
||||||
database: "foo",
|
database: "foo",
|
||||||
encoding: "utf8",
|
encoding: "utf8",
|
||||||
name: "production"
|
name: "production"
|
||||||
}, role)
|
}, pool_config)
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_role_connection_specification_name_on_key_lookup
|
def test_pool_config_connection_specification_name_on_key_lookup
|
||||||
role = resolve_role(:readonly, "readonly" => { "adapter" => "sqlite3" })
|
pool_config = resolve_pool_config(:readonly, "readonly" => { "adapter" => "sqlite3" })
|
||||||
assert_equal "readonly", role.connection_specification_name
|
assert_equal "readonly", pool_config.connection_specification_name
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_role_connection_specification_name_with_inline_config
|
def test_pool_config_connection_specification_name_with_inline_config
|
||||||
role = resolve_role("adapter" => "sqlite3")
|
pool_config = resolve_pool_config("adapter" => "sqlite3")
|
||||||
assert_equal "primary", role.connection_specification_name, "should default to primary id"
|
assert_equal "primary", pool_config.connection_specification_name, "should default to primary id"
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_role_with_invalid_type
|
def test_pool_config_with_invalid_type
|
||||||
assert_raises TypeError do
|
assert_raises TypeError do
|
||||||
resolve_role(Object.new)
|
resolve_pool_config(Object.new)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
|
@ -555,10 +555,10 @@ class QueryCacheTest < ActiveRecord::TestCase
|
||||||
|
|
||||||
private
|
private
|
||||||
def with_temporary_connection_pool
|
def with_temporary_connection_pool
|
||||||
role = ActiveRecord::Base.connection_handler.send(:owner_to_role_manager).fetch("primary").get_role(:default)
|
pool_config = ActiveRecord::Base.connection_handler.send(:owner_to_pool_manager).fetch("primary").get_pool_config(:default)
|
||||||
new_pool = ActiveRecord::ConnectionAdapters::ConnectionPool.new(role)
|
new_pool = ActiveRecord::ConnectionAdapters::ConnectionPool.new(pool_config)
|
||||||
|
|
||||||
role.stub(:pool, new_pool) do
|
pool_config.stub(:pool, new_pool) do
|
||||||
yield
|
yield
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -59,8 +59,8 @@ module ActiveRecord
|
||||||
|
|
||||||
def test_pool_has_reaper
|
def test_pool_has_reaper
|
||||||
config = ActiveRecord::Base.configurations.configs_for(env_name: "arunit", spec_name: "primary")
|
config = ActiveRecord::Base.configurations.configs_for(env_name: "arunit", spec_name: "primary")
|
||||||
role = Role.new("primary", config)
|
pool_config = PoolConfig.new("primary", config)
|
||||||
pool = ConnectionPool.new(role)
|
pool = ConnectionPool.new(pool_config)
|
||||||
|
|
||||||
assert pool.reaper
|
assert pool.reaper
|
||||||
ensure
|
ensure
|
||||||
|
@ -68,10 +68,10 @@ module ActiveRecord
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_reaping_frequency_configuration
|
def test_reaping_frequency_configuration
|
||||||
role = duplicated_role
|
pool_config = duplicated_pool_config
|
||||||
role.db_config.configuration_hash[:reaping_frequency] = "10.01"
|
pool_config.db_config.configuration_hash[:reaping_frequency] = "10.01"
|
||||||
|
|
||||||
pool = ConnectionPool.new(role)
|
pool = ConnectionPool.new(pool_config)
|
||||||
|
|
||||||
assert_equal 10.01, pool.reaper.frequency
|
assert_equal 10.01, pool.reaper.frequency
|
||||||
ensure
|
ensure
|
||||||
|
@ -79,10 +79,10 @@ module ActiveRecord
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_connection_pool_starts_reaper
|
def test_connection_pool_starts_reaper
|
||||||
role = duplicated_role
|
pool_config = duplicated_pool_config
|
||||||
role.db_config.configuration_hash[:reaping_frequency] = "0.0001"
|
pool_config.db_config.configuration_hash[:reaping_frequency] = "0.0001"
|
||||||
|
|
||||||
pool = ConnectionPool.new(role)
|
pool = ConnectionPool.new(pool_config)
|
||||||
|
|
||||||
conn, child = new_conn_in_thread(pool)
|
conn, child = new_conn_in_thread(pool)
|
||||||
|
|
||||||
|
@ -97,11 +97,11 @@ module ActiveRecord
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_reaper_works_after_pool_discard
|
def test_reaper_works_after_pool_discard
|
||||||
role = duplicated_role
|
pool_config = duplicated_pool_config
|
||||||
role.db_config.configuration_hash[:reaping_frequency] = "0.0001"
|
pool_config.db_config.configuration_hash[:reaping_frequency] = "0.0001"
|
||||||
|
|
||||||
2.times do
|
2.times do
|
||||||
pool = ConnectionPool.new(role)
|
pool = ConnectionPool.new(pool_config)
|
||||||
|
|
||||||
conn, child = new_conn_in_thread(pool)
|
conn, child = new_conn_in_thread(pool)
|
||||||
|
|
||||||
|
@ -119,8 +119,8 @@ module ActiveRecord
|
||||||
# This doesn't test the reaper directly, but we want to test the action
|
# This doesn't test the reaper directly, but we want to test the action
|
||||||
# it would take on a discarded pool
|
# it would take on a discarded pool
|
||||||
def test_reap_flush_on_discarded_pool
|
def test_reap_flush_on_discarded_pool
|
||||||
role = duplicated_role
|
pool_config = duplicated_pool_config
|
||||||
pool = ConnectionPool.new(role)
|
pool = ConnectionPool.new(pool_config)
|
||||||
|
|
||||||
pool.discard!
|
pool.discard!
|
||||||
pool.reap
|
pool.reap
|
||||||
|
@ -128,14 +128,14 @@ module ActiveRecord
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_connection_pool_starts_reaper_in_fork
|
def test_connection_pool_starts_reaper_in_fork
|
||||||
role = duplicated_role
|
pool_config = duplicated_pool_config
|
||||||
role.db_config.configuration_hash[:reaping_frequency] = "0.0001"
|
pool_config.db_config.configuration_hash[:reaping_frequency] = "0.0001"
|
||||||
|
|
||||||
pool = ConnectionPool.new(role)
|
pool = ConnectionPool.new(pool_config)
|
||||||
pool.checkout
|
pool.checkout
|
||||||
|
|
||||||
pid = fork do
|
pid = fork do
|
||||||
pool = ConnectionPool.new(role)
|
pool = ConnectionPool.new(pool_config)
|
||||||
|
|
||||||
conn, child = new_conn_in_thread(pool)
|
conn, child = new_conn_in_thread(pool)
|
||||||
child.terminate
|
child.terminate
|
||||||
|
@ -173,10 +173,10 @@ module ActiveRecord
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
def duplicated_role
|
def duplicated_pool_config
|
||||||
old_config = ActiveRecord::Base.connection_pool.db_config.configuration_hash
|
old_config = ActiveRecord::Base.connection_pool.db_config.configuration_hash
|
||||||
db_config = ActiveRecord::DatabaseConfigurations::HashConfig.new("arunit", "primary", old_config.dup)
|
db_config = ActiveRecord::DatabaseConfigurations::HashConfig.new("arunit", "primary", old_config.dup)
|
||||||
Role.new("primary", db_config)
|
PoolConfig.new("primary", db_config)
|
||||||
end
|
end
|
||||||
|
|
||||||
def new_conn_in_thread(pool)
|
def new_conn_in_thread(pool)
|
||||||
|
|
|
@ -13,7 +13,7 @@ class TestUnconnectedAdapter < ActiveRecord::TestCase
|
||||||
@specification = ActiveRecord::Base.remove_connection
|
@specification = ActiveRecord::Base.remove_connection
|
||||||
|
|
||||||
# Clear out connection info from other pids (like a fork parent) too
|
# Clear out connection info from other pids (like a fork parent) too
|
||||||
ActiveRecord::ConnectionAdapters::Role.discard_pools!
|
ActiveRecord::ConnectionAdapters::PoolConfig.discard_pools!
|
||||||
end
|
end
|
||||||
|
|
||||||
teardown do
|
teardown do
|
||||||
|
|
Loading…
Reference in a new issue