Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
张重言
rails
提交
74688afe
R
rails
项目概览
张重言
/
rails
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
R
rails
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
未验证
提交
74688afe
编写于
11月 07, 2019
作者:
E
Eileen M. Uchitelle
提交者:
GitHub
11月 07, 2019
浏览文件
操作
浏览文件
下载
差异文件
Merge pull request #37622 from eileencodes/multi-role-per-class
Add an intermediary called RoleManager to manage connections
上级
789fa4d9
6d81eab1
变更
15
隐藏空白更改
内联
并排
Showing
15 changed file
with
267 addition
and
121 deletion
+267
-121
activerecord/lib/active_record/connection_adapters.rb
activerecord/lib/active_record/connection_adapters.rb
+2
-1
activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb
...ve_record/connection_adapters/abstract/connection_pool.rb
+35
-28
activerecord/lib/active_record/connection_adapters/pool_config.rb
...cord/lib/active_record/connection_adapters/pool_config.rb
+2
-2
activerecord/lib/active_record/connection_adapters/pool_manager.rb
...ord/lib/active_record/connection_adapters/pool_manager.rb
+27
-0
activerecord/lib/active_record/connection_adapters/resolver.rb
...erecord/lib/active_record/connection_adapters/resolver.rb
+6
-6
activerecord/lib/active_record/test_fixtures.rb
activerecord/lib/active_record/test_fixtures.rb
+5
-1
activerecord/test/cases/connection_adapters/adapter_leasing_test.rb
...rd/test/cases/connection_adapters/adapter_leasing_test.rb
+2
-2
activerecord/test/cases/connection_adapters/connection_handlers_multi_pool_config_test.rb
...on_adapters/connection_handlers_multi_pool_config_test.rb
+107
-0
activerecord/test/cases/connection_pool_test.rb
activerecord/test/cases/connection_pool_test.rb
+12
-12
activerecord/test/cases/disconnected_test.rb
activerecord/test/cases/disconnected_test.rb
+2
-2
activerecord/test/cases/fixtures_test.rb
activerecord/test/cases/fixtures_test.rb
+3
-3
activerecord/test/cases/pool_config/resolver_test.rb
activerecord/test/cases/pool_config/resolver_test.rb
+41
-41
activerecord/test/cases/query_cache_test.rb
activerecord/test/cases/query_cache_test.rb
+3
-3
activerecord/test/cases/reaper_test.rb
activerecord/test/cases/reaper_test.rb
+19
-19
activerecord/test/cases/unconnected_test.rb
activerecord/test/cases/unconnected_test.rb
+1
-1
未找到文件。
activerecord/lib/active_record/connection_adapters.rb
浏览文件 @
74688afe
...
...
@@ -9,7 +9,8 @@ module ConnectionAdapters
end
autoload
:Column
autoload
:Role
autoload
:PoolConfig
autoload
:PoolManager
autoload
:Resolver
autoload_at
"active_record/connection_adapters/abstract/schema_definitions"
do
...
...
activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb
浏览文件 @
74688afe
...
...
@@ -370,21 +370,21 @@ def run
include
ConnectionAdapters
::
AbstractPool
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,
# host name, username, password, etc), as well as the maximum size for
# this ConnectionPool.
#
# The default ConnectionPool maximum size is 5.
def
initialize
(
role
)
def
initialize
(
pool_config
)
super
()
@
role
=
role
@db_config
=
role
.
db_config
@
pool_config
=
pool_config
@db_config
=
pool_config
.
db_config
@checkout_timeout
=
db_config
.
checkout_timeout
@idle_timeout
=
db_config
.
idle_timeout
...
...
@@ -1003,8 +1003,8 @@ class ConnectionHandler
private_constant
:FINALIZER
def
initialize
# These caches are keyed by
role.connection_specification_name (Role
#connection_specification_name).
@owner_to_
role
=
Concurrent
::
Map
.
new
(
initial_capacity:
2
)
# These caches are keyed by
pool_config.connection_specification_name (PoolConfig
#connection_specification_name).
@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
ObjectSpace
.
define_finalizer
self
,
FINALIZER
...
...
@@ -1031,34 +1031,36 @@ def while_preventing_writes(enabled = true)
end
def
connection_pool_names
# :nodoc:
owner_to_
role
.
keys
owner_to_
pool_manager
.
keys
end
def
connection_pool_list
owner_to_
role
.
values
.
compact
.
map
(
&
:pool
)
owner_to_
pool_manager
.
values
.
compact
.
flat_map
{
|
m
|
m
.
pool_configs
.
map
(
&
:pool
)
}
end
alias
:connection_pools
:connection_pool_list
def
establish_connection
(
config
)
def
establish_connection
(
config
,
pool_key
=
:default
)
resolver
=
Resolver
.
new
(
Base
.
configurations
)
role
=
resolver
.
resolve_role
(
config
)
db_config
=
role
.
db_config
pool_config
=
resolver
.
resolve_pool_config
(
config
)
db_config
=
pool_config
.
db_config
remove_connection
(
role
.
connection_specification_name
)
remove_connection
(
pool_config
.
connection_specification_name
,
pool_key
)
message_bus
=
ActiveSupport
::
Notifications
.
instrumenter
payload
=
{
connection_id:
object_id
}
if
role
payload
[
:spec_name
]
=
role
.
connection_specification_name
if
pool_config
payload
[
:spec_name
]
=
pool_config
.
connection_specification_name
payload
[
:config
]
=
db_config
.
configuration_hash
end
owner_to_role
[
role
.
connection_specification_name
]
=
role
owner_to_pool_manager
[
pool_config
.
connection_specification_name
]
||=
PoolManager
.
new
pool_manager
=
owner_to_pool_manager
[
pool_config
.
connection_specification_name
]
pool_manager
.
set_pool_config
(
pool_key
,
pool_config
)
message_bus
.
instrument
(
"!connection.active_record"
,
payload
)
do
role
.
pool
pool_config
.
pool
end
end
...
...
@@ -1114,8 +1116,8 @@ def retrieve_connection(spec_name) #:nodoc:
# Returns true if a connection that's accessible to this class has
# already been opened.
def
connected?
(
spec_name
)
pool
=
retrieve_connection_pool
(
spec_name
)
def
connected?
(
spec_name
,
pool_key
=
:default
)
pool
=
retrieve_connection_pool
(
spec_name
,
pool_key
)
pool
&&
pool
.
connected?
end
...
...
@@ -1123,22 +1125,27 @@ def connected?(spec_name)
# connection and the defined connection (if they exist). The result
# can be used as an argument for #establish_connection, for easily
# re-establishing the connection.
def
remove_connection
(
spec_name
)
if
role
=
owner_to_role
.
delete
(
spec_name
)
role
.
disconnect!
role
.
db_config
.
configuration_hash
def
remove_connection
(
spec_name
,
pool_key
=
:default
)
if
pool_manager
=
owner_to_pool_manager
[
spec_name
]
pool_config
=
pool_manager
.
remove_pool_config
(
pool_key
)
if
pool_config
pool_config
.
disconnect!
pool_config
.
db_config
.
configuration_hash
end
end
end
# Retrieving the connection pool happens a lot, so we cache it in @owner_to_
role
.
# 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.
# When a connection is established or removed, we invalidate the cache.
def
retrieve_connection_pool
(
spec_name
)
owner_to_role
[
spec_name
]
&
.
pool
def
retrieve_connection_pool
(
spec_name
,
pool_key
=
:default
)
pool_config
=
owner_to_pool_manager
[
spec_name
]
&
.
get_pool_config
(
pool_key
)
pool_config
&
.
pool
end
private
attr_reader
:owner_to_
role
attr_reader
:owner_to_
pool_manager
end
end
end
activerecord/lib/active_record/connection_adapters/
role
.rb
→
activerecord/lib/active_record/connection_adapters/
pool_config
.rb
浏览文件 @
74688afe
...
...
@@ -2,7 +2,7 @@
module
ActiveRecord
module
ConnectionAdapters
class
Role
# :nodoc:
class
PoolConfig
# :nodoc:
include
Mutex_m
attr_reader
:db_config
,
:connection_specification_name
...
...
@@ -60,4 +60,4 @@ def discard_pool!
end
end
ActiveSupport
::
ForkTracker
.
after_fork
{
ActiveRecord
::
ConnectionAdapters
::
Role
.
discard_pools!
}
ActiveSupport
::
ForkTracker
.
after_fork
{
ActiveRecord
::
ConnectionAdapters
::
PoolConfig
.
discard_pools!
}
activerecord/lib/active_record/connection_adapters/pool_manager.rb
0 → 100644
浏览文件 @
74688afe
# 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
activerecord/lib/active_record/connection_adapters/resolver.rb
浏览文件 @
74688afe
...
...
@@ -2,7 +2,7 @@
module
ActiveRecord
module
ConnectionAdapters
# Builds a
Role
from user input.
# Builds a
PoolConfig
from user input.
class
Resolver
# :nodoc:
attr_reader
:configurations
...
...
@@ -11,17 +11,17 @@ def initialize(configurations)
@configurations
=
configurations
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.
#
# == Example
#
# config = { "production" => { "host" => "localhost", "database" => "foo", "adapter" => "sqlite3" } }
#
role = Resolver.new(config).resolve_role
(:production)
#
role
.db_config.configuration_hash
#
pool_config = Resolver.new(config).resolve_pool_config
(:production)
#
pool_config
.db_config.configuration_hash
# # => { host: "localhost", database: "foo", adapter: "sqlite3" }
#
def
resolve_
role
(
config
)
def
resolve_
pool_config
(
config
)
pool_name
=
config
if
config
.
is_a?
(
Symbol
)
db_config
=
resolve
(
config
,
pool_name
)
...
...
@@ -53,7 +53,7 @@ def resolve_role(config)
raise
AdapterNotFound
,
"database configuration specifies nonexistent
#{
db_config
.
adapter
}
adapter"
end
Role
.
new
(
db_config
.
configuration_hash
.
delete
(
:name
)
||
"primary"
,
db_config
)
PoolConfig
.
new
(
db_config
.
configuration_hash
.
delete
(
:name
)
||
"primary"
,
db_config
)
end
# Returns fully resolved connection, accepts hash, string or symbol.
...
...
activerecord/lib/active_record/test_fixtures.rb
浏览文件 @
74688afe
...
...
@@ -192,7 +192,11 @@ def setup_shared_connection_pool
ActiveRecord
::
Base
.
connection_handlers
.
values
.
each
do
|
handler
|
if
handler
!=
writing_handler
handler
.
connection_pool_names
.
each
do
|
name
|
handler
.
send
(
:owner_to_role
)[
name
]
=
writing_handler
.
send
(
:owner_to_role
)[
name
]
writing_pool_manager
=
writing_handler
.
send
(
:owner_to_pool_manager
)[
name
]
writing_pool_config
=
writing_pool_manager
.
get_pool_config
(
:default
)
pool_manager
=
handler
.
send
(
:owner_to_pool_manager
)[
name
]
pool_manager
.
set_pool_config
(
:default
,
writing_pool_config
)
end
end
end
...
...
activerecord/test/cases/connection_adapters/adapter_leasing_test.rb
浏览文件 @
74688afe
...
...
@@ -40,8 +40,8 @@ def test_expire_mutates_in_use
def
test_close
db_config
=
ActiveRecord
::
DatabaseConfigurations
::
HashConfig
.
new
(
"test"
,
"primary"
,
{})
role
=
ActiveRecord
::
ConnectionAdapters
::
Role
.
new
(
"primary"
,
db_config
)
pool
=
Pool
.
new
(
role
)
pool_config
=
ActiveRecord
::
ConnectionAdapters
::
PoolConfig
.
new
(
"primary"
,
db_config
)
pool
=
Pool
.
new
(
pool_config
)
pool
.
insert_connection_for_test!
@adapter
@adapter
.
pool
=
pool
...
...
activerecord/test/cases/connection_adapters/connection_handlers_multi_pool_config_test.rb
0 → 100644
浏览文件 @
74688afe
# frozen_string_literal: true
require
"cases/helper"
require
"models/person"
module
ActiveRecord
module
ConnectionAdapters
class
ConnectionHandlersMultiPoolConfigTest
<
ActiveRecord
::
TestCase
self
.
use_transactional_tests
=
false
fixtures
:people
def
setup
@handlers
=
{
writing:
ConnectionHandler
.
new
}
@rw_handler
=
@handlers
[
:writing
]
@spec_name
=
"primary"
@writing_handler
=
ActiveRecord
::
Base
.
connection_handlers
[
:writing
]
end
def
teardown
ActiveRecord
::
Base
.
connection_handlers
=
{
writing:
ActiveRecord
::
Base
.
default_connection_handler
}
end
unless
in_memory_db?
def
test_establish_connection_with_pool_configs
previous_env
,
ENV
[
"RAILS_ENV"
]
=
ENV
[
"RAILS_ENV"
],
"default_env"
config
=
{
"default_env"
=>
{
"primary"
=>
{
"adapter"
=>
"sqlite3"
,
"database"
=>
"db/primary.sqlite3"
}
}
}
@prev_configs
,
ActiveRecord
::
Base
.
configurations
=
ActiveRecord
::
Base
.
configurations
,
config
@writing_handler
.
establish_connection
(
:primary
)
@writing_handler
.
establish_connection
(
:primary
,
:pool_config_two
)
default_pool
=
@writing_handler
.
retrieve_connection_pool
(
"primary"
,
:default
)
other_pool
=
@writing_handler
.
retrieve_connection_pool
(
"primary"
,
:pool_config_two
)
assert_not_nil
default_pool
assert_not_equal
default_pool
,
other_pool
# :default if passed with no key
assert_equal
default_pool
,
@writing_handler
.
retrieve_connection_pool
(
"primary"
)
ensure
ActiveRecord
::
Base
.
configurations
=
@prev_configs
ActiveRecord
::
Base
.
establish_connection
(
:arunit
)
ENV
[
"RAILS_ENV"
]
=
previous_env
end
def
test_remove_connection
previous_env
,
ENV
[
"RAILS_ENV"
]
=
ENV
[
"RAILS_ENV"
],
"default_env"
config
=
{
"default_env"
=>
{
"primary"
=>
{
"adapter"
=>
"sqlite3"
,
"database"
=>
"db/primary.sqlite3"
}
}
}
@prev_configs
,
ActiveRecord
::
Base
.
configurations
=
ActiveRecord
::
Base
.
configurations
,
config
@writing_handler
.
establish_connection
(
:primary
)
@writing_handler
.
establish_connection
(
:primary
,
:pool_config_two
)
# remove default
@writing_handler
.
remove_connection
(
"primary"
)
assert_nil
@writing_handler
.
retrieve_connection_pool
(
"primary"
)
assert_not_nil
@writing_handler
.
retrieve_connection_pool
(
"primary"
,
:pool_config_two
)
ensure
ActiveRecord
::
Base
.
configurations
=
@prev_configs
ActiveRecord
::
Base
.
establish_connection
(
:arunit
)
ENV
[
"RAILS_ENV"
]
=
previous_env
end
def
test_connected?
previous_env
,
ENV
[
"RAILS_ENV"
]
=
ENV
[
"RAILS_ENV"
],
"default_env"
config
=
{
"default_env"
=>
{
"primary"
=>
{
"adapter"
=>
"sqlite3"
,
"database"
=>
"db/primary.sqlite3"
}
}
}
@prev_configs
,
ActiveRecord
::
Base
.
configurations
=
ActiveRecord
::
Base
.
configurations
,
config
@writing_handler
.
establish_connection
(
:primary
)
@writing_handler
.
establish_connection
(
:primary
,
:pool_config_two
)
# connect to default
@writing_handler
.
connection_pool_list
.
first
.
checkout
assert
@writing_handler
.
connected?
(
"primary"
)
assert
@writing_handler
.
connected?
(
"primary"
,
:default
)
assert_not
@writing_handler
.
connected?
(
"primary"
,
:pool_config_two
)
ensure
ActiveRecord
::
Base
.
configurations
=
@prev_configs
ActiveRecord
::
Base
.
establish_connection
(
:arunit
)
ENV
[
"RAILS_ENV"
]
=
previous_env
FileUtils
.
rm_rf
"db"
end
end
end
end
end
activerecord/test/cases/connection_pool_test.rb
浏览文件 @
74688afe
...
...
@@ -13,8 +13,8 @@ def setup
# Keep a duplicate pool so we do not bother others
@db_config
=
ActiveRecord
::
Base
.
connection_pool
.
db_config
@
role
=
ActiveRecord
::
ConnectionAdapters
::
Role
.
new
(
"primary"
,
@db_config
)
@pool
=
ConnectionPool
.
new
(
@
role
)
@
pool_config
=
ActiveRecord
::
ConnectionAdapters
::
PoolConfig
.
new
(
"primary"
,
@db_config
)
@pool
=
ConnectionPool
.
new
(
@
pool_config
)
if
in_memory_db?
# Separate connections to an in-memory database create an entirely new database,
...
...
@@ -201,8 +201,8 @@ def test_reap_inactive
def
test_idle_timeout_configuration
@pool
.
disconnect!
@db_config
.
configuration_hash
.
merge!
(
idle_timeout:
"0.02"
)
role
=
ActiveRecord
::
ConnectionAdapters
::
Role
.
new
(
"primary"
,
@db_config
)
@pool
=
ConnectionPool
.
new
(
role
)
pool_config
=
ActiveRecord
::
ConnectionAdapters
::
PoolConfig
.
new
(
"primary"
,
@db_config
)
@pool
=
ConnectionPool
.
new
(
pool_config
)
idle_conn
=
@pool
.
checkout
@pool
.
checkin
(
idle_conn
)
...
...
@@ -226,8 +226,8 @@ def test_idle_timeout_configuration
def
test_disable_flush
@pool
.
disconnect!
@db_config
.
configuration_hash
.
merge!
(
idle_timeout:
-
5
)
role
=
ActiveRecord
::
ConnectionAdapters
::
Role
.
new
(
"primary"
,
@db_config
)
@pool
=
ConnectionPool
.
new
(
role
)
pool_config
=
ActiveRecord
::
ConnectionAdapters
::
PoolConfig
.
new
(
"primary"
,
@db_config
)
@pool
=
ConnectionPool
.
new
(
pool_config
)
idle_conn
=
@pool
.
checkout
@pool
.
checkin
(
idle_conn
)
...
...
@@ -317,7 +317,7 @@ def test_active_connection?
end
def
test_checkout_behaviour
pool
=
ConnectionPool
.
new
(
@
role
)
pool
=
ConnectionPool
.
new
(
@
pool_config
)
main_connection
=
pool
.
connection
assert_not_nil
main_connection
threads
=
[]
...
...
@@ -450,7 +450,7 @@ def test_checkout_fairness_by_group
end
def
test_automatic_reconnect_restores_after_disconnect
pool
=
ConnectionPool
.
new
(
@
role
)
pool
=
ConnectionPool
.
new
(
@
pool_config
)
assert
pool
.
automatic_reconnect
assert
pool
.
connection
...
...
@@ -459,7 +459,7 @@ def test_automatic_reconnect_restores_after_disconnect
end
def
test_automatic_reconnect_can_be_disabled
pool
=
ConnectionPool
.
new
(
@
role
)
pool
=
ConnectionPool
.
new
(
@
pool_config
)
pool
.
disconnect!
pool
.
automatic_reconnect
=
false
...
...
@@ -723,10 +723,10 @@ def with_single_connection_pool
old_config
=
@db_config
.
configuration_hash
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
)
yield
(
pool
=
ConnectionPool
.
new
(
role
))
pool_config
=
ActiveRecord
::
ConnectionAdapters
::
PoolConfig
.
new
(
"primary"
,
db_config
)
yield
(
pool
=
ConnectionPool
.
new
(
pool_config
))
ensure
pool
.
disconnect!
if
pool
end
...
...
activerecord/test/cases/disconnected_test.rb
浏览文件 @
74688afe
...
...
@@ -14,8 +14,8 @@ def setup
teardown
do
return
if
in_memory_db?
role
=
ActiveRecord
::
Base
.
connection_config
ActiveRecord
::
Base
.
establish_connection
(
role
)
config
=
ActiveRecord
::
Base
.
connection_config
ActiveRecord
::
Base
.
establish_connection
(
config
)
end
unless
in_memory_db?
...
...
activerecord/test/cases/fixtures_test.rb
浏览文件 @
74688afe
...
...
@@ -1414,10 +1414,10 @@ class MultipleDatabaseFixturesTest < ActiveRecord::TestCase
private
def
with_temporary_connection_pool
role
=
ActiveRecord
::
Base
.
connection_handler
.
send
(
:owner_to_role
).
fetch
(
"primary"
)
new_pool
=
ActiveRecord
::
ConnectionAdapters
::
ConnectionPool
.
new
(
role
)
pool_config
=
ActiveRecord
::
Base
.
connection_handler
.
send
(
:owner_to_pool_manager
).
fetch
(
"primary"
).
get_pool_config
(
:default
)
new_pool
=
ActiveRecord
::
ConnectionAdapters
::
ConnectionPool
.
new
(
pool_config
)
role
.
stub
(
:pool
,
new_pool
)
do
pool_config
.
stub
(
:pool
,
new_pool
)
do
yield
end
end
...
...
activerecord/test/cases/
connection_specification
/resolver_test.rb
→
activerecord/test/cases/
pool_config
/resolver_test.rb
浏览文件 @
74688afe
...
...
@@ -4,23 +4,23 @@
module
ActiveRecord
module
ConnectionAdapters
class
Role
class
PoolConfig
class
ResolverTest
<
ActiveRecord
::
TestCase
def
resolve
(
role
,
config
=
{})
def
resolve
(
pool_config
,
config
=
{})
configs
=
ActiveRecord
::
DatabaseConfigurations
.
new
(
config
)
resolver
=
ConnectionAdapters
::
Resolver
.
new
(
configs
)
resolver
.
resolve
(
role
,
role
).
configuration_hash
resolver
.
resolve
(
pool_config
,
pool_config
).
configuration_hash
end
def
resolve_
role
(
role
,
config
=
{})
def
resolve_
pool_config
(
pool_config
,
config
=
{})
configs
=
ActiveRecord
::
DatabaseConfigurations
.
new
(
config
)
resolver
=
ConnectionAdapters
::
Resolver
.
new
(
configs
)
resolver
.
resolve_
role
(
role
)
resolver
.
resolve_
pool_config
(
pool_config
)
end
def
test_url_invalid_adapter
error
=
assert_raises
(
LoadError
)
do
resolve_
role
"ridiculous://foo?encoding=utf8"
resolve_
pool_config
"ridiculous://foo?encoding=utf8"
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
...
...
@@ -28,7 +28,7 @@ def test_url_invalid_adapter
def
test_error_if_no_adapter_method
error
=
assert_raises
(
AdapterNotFound
)
do
resolve_
role
"abstract://foo?encoding=utf8"
resolve_
pool_config
"abstract://foo?encoding=utf8"
end
assert_match
"database configuration specifies nonexistent abstract adapter"
,
error
.
message
...
...
@@ -38,121 +38,121 @@ def test_error_if_no_adapter_method
# checks that the adapter file can be required in.
def
test_url_from_environment
role
=
resolve
:production
,
"production"
=>
"abstract://foo?encoding=utf8"
pool_config
=
resolve
:production
,
"production"
=>
"abstract://foo?encoding=utf8"
assert_equal
({
adapter:
"abstract"
,
host:
"foo"
,
encoding:
"utf8"
,
name:
"production"
},
role
)
},
pool_config
)
end
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
({
adapter:
"abstract"
,
host:
"foo"
,
encoding:
"utf8"
,
name:
"production"
},
role
)
},
pool_config
)
end
def
test_url_sub_key_merges_correctly
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
({
adapter:
"abstract"
,
host:
"foo"
,
encoding:
"utf8"
,
pool:
"3"
,
name:
"production"
},
role
)
},
pool_config
)
end
def
test_url_host_no_db
role
=
resolve
"abstract://foo?encoding=utf8"
pool_config
=
resolve
"abstract://foo?encoding=utf8"
assert_equal
({
adapter:
"abstract"
,
host:
"foo"
,
encoding:
"utf8"
},
role
)
},
pool_config
)
end
def
test_url_missing_scheme
role
=
resolve
"foo"
assert_equal
({
database:
"foo"
},
role
)
pool_config
=
resolve
"foo"
assert_equal
({
database:
"foo"
},
pool_config
)
end
def
test_url_host_db
role
=
resolve
"abstract://foo/bar?encoding=utf8"
pool_config
=
resolve
"abstract://foo/bar?encoding=utf8"
assert_equal
({
adapter:
"abstract"
,
database:
"bar"
,
host:
"foo"
,
encoding:
"utf8"
},
role
)
},
pool_config
)
end
def
test_url_port
role
=
resolve
"abstract://foo:123?encoding=utf8"
pool_config
=
resolve
"abstract://foo:123?encoding=utf8"
assert_equal
({
adapter:
"abstract"
,
port:
123
,
host:
"foo"
,
encoding:
"utf8"
},
role
)
},
pool_config
)
end
def
test_encoded_password
password
=
"am@z1ng_p@ssw0rd#!"
encoded_password
=
URI
.
encode_www_form_component
(
password
)
role
=
resolve
"abstract://foo:
#{
encoded_password
}
@localhost/bar"
assert_equal
password
,
role
[
:password
]
pool_config
=
resolve
"abstract://foo:
#{
encoded_password
}
@localhost/bar"
assert_equal
password
,
pool_config
[
:password
]
end
def
test_url_with_authority_for_sqlite3
role
=
resolve
"sqlite3:///foo_test"
assert_equal
(
"/foo_test"
,
role
[
:database
])
pool_config
=
resolve
"sqlite3:///foo_test"
assert_equal
(
"/foo_test"
,
pool_config
[
:database
])
end
def
test_url_absolute_path_for_sqlite3
role
=
resolve
"sqlite3:/foo_test"
assert_equal
(
"/foo_test"
,
role
[
:database
])
pool_config
=
resolve
"sqlite3:/foo_test"
assert_equal
(
"/foo_test"
,
pool_config
[
:database
])
end
def
test_url_relative_path_for_sqlite3
role
=
resolve
"sqlite3:foo_test"
assert_equal
(
"foo_test"
,
role
[
:database
])
pool_config
=
resolve
"sqlite3:foo_test"
assert_equal
(
"foo_test"
,
pool_config
[
:database
])
end
def
test_url_memory_db_for_sqlite3
role
=
resolve
"sqlite3::memory:"
assert_equal
(
":memory:"
,
role
[
:database
])
pool_config
=
resolve
"sqlite3::memory:"
assert_equal
(
":memory:"
,
pool_config
[
:database
])
end
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
({
adapter:
"sqlite3"
,
database:
"foo"
,
encoding:
"utf8"
,
name:
"production"
},
role
)
},
pool_config
)
end
def
test_
role
_connection_specification_name_on_key_lookup
role
=
resolve_role
(
:readonly
,
"readonly"
=>
{
"adapter"
=>
"sqlite3"
})
assert_equal
"readonly"
,
role
.
connection_specification_name
def
test_
pool_config
_connection_specification_name_on_key_lookup
pool_config
=
resolve_pool_config
(
:readonly
,
"readonly"
=>
{
"adapter"
=>
"sqlite3"
})
assert_equal
"readonly"
,
pool_config
.
connection_specification_name
end
def
test_
role
_connection_specification_name_with_inline_config
role
=
resolve_role
(
"adapter"
=>
"sqlite3"
)
assert_equal
"primary"
,
role
.
connection_specification_name
,
"should default to primary id"
def
test_
pool_config
_connection_specification_name_with_inline_config
pool_config
=
resolve_pool_config
(
"adapter"
=>
"sqlite3"
)
assert_equal
"primary"
,
pool_config
.
connection_specification_name
,
"should default to primary id"
end
def
test_
role
_with_invalid_type
def
test_
pool_config
_with_invalid_type
assert_raises
TypeError
do
resolve_
role
(
Object
.
new
)
resolve_
pool_config
(
Object
.
new
)
end
end
end
...
...
activerecord/test/cases/query_cache_test.rb
浏览文件 @
74688afe
...
...
@@ -555,10 +555,10 @@ def test_clear_query_cache_is_called_on_all_connections
private
def
with_temporary_connection_pool
role
=
ActiveRecord
::
Base
.
connection_handler
.
send
(
:owner_to_role
).
fetch
(
"primary"
)
new_pool
=
ActiveRecord
::
ConnectionAdapters
::
ConnectionPool
.
new
(
role
)
pool_config
=
ActiveRecord
::
Base
.
connection_handler
.
send
(
:owner_to_pool_manager
).
fetch
(
"primary"
).
get_pool_config
(
:default
)
new_pool
=
ActiveRecord
::
ConnectionAdapters
::
ConnectionPool
.
new
(
pool_config
)
role
.
stub
(
:pool
,
new_pool
)
do
pool_config
.
stub
(
:pool
,
new_pool
)
do
yield
end
end
...
...
activerecord/test/cases/reaper_test.rb
浏览文件 @
74688afe
...
...
@@ -59,8 +59,8 @@ def test_some_time
def
test_pool_has_reaper
config
=
ActiveRecord
::
Base
.
configurations
.
configs_for
(
env_name:
"arunit"
,
spec_name:
"primary"
)
role
=
Role
.
new
(
"primary"
,
config
)
pool
=
ConnectionPool
.
new
(
role
)
pool_config
=
PoolConfig
.
new
(
"primary"
,
config
)
pool
=
ConnectionPool
.
new
(
pool_config
)
assert
pool
.
reaper
ensure
...
...
@@ -68,10 +68,10 @@ def test_pool_has_reaper
end
def
test_reaping_frequency_configuration
role
=
duplicated_role
role
.
db_config
.
configuration_hash
[
:reaping_frequency
]
=
"10.01"
pool_config
=
duplicated_pool_config
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
ensure
...
...
@@ -79,10 +79,10 @@ def test_reaping_frequency_configuration
end
def
test_connection_pool_starts_reaper
role
=
duplicated_role
role
.
db_config
.
configuration_hash
[
:reaping_frequency
]
=
"0.0001"
pool_config
=
duplicated_pool_config
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
)
...
...
@@ -97,11 +97,11 @@ def test_connection_pool_starts_reaper
end
def
test_reaper_works_after_pool_discard
role
=
duplicated_role
role
.
db_config
.
configuration_hash
[
:reaping_frequency
]
=
"0.0001"
pool_config
=
duplicated_pool_config
pool_config
.
db_config
.
configuration_hash
[
:reaping_frequency
]
=
"0.0001"
2
.
times
do
pool
=
ConnectionPool
.
new
(
role
)
pool
=
ConnectionPool
.
new
(
pool_config
)
conn
,
child
=
new_conn_in_thread
(
pool
)
...
...
@@ -119,8 +119,8 @@ def test_reaper_works_after_pool_discard
# This doesn't test the reaper directly, but we want to test the action
# it would take on a discarded pool
def
test_reap_flush_on_discarded_pool
role
=
duplicated_role
pool
=
ConnectionPool
.
new
(
role
)
pool_config
=
duplicated_pool_config
pool
=
ConnectionPool
.
new
(
pool_config
)
pool
.
discard!
pool
.
reap
...
...
@@ -128,14 +128,14 @@ def test_reap_flush_on_discarded_pool
end
def
test_connection_pool_starts_reaper_in_fork
role
=
duplicated_role
role
.
db_config
.
configuration_hash
[
:reaping_frequency
]
=
"0.0001"
pool_config
=
duplicated_pool_config
pool_config
.
db_config
.
configuration_hash
[
:reaping_frequency
]
=
"0.0001"
pool
=
ConnectionPool
.
new
(
role
)
pool
=
ConnectionPool
.
new
(
pool_config
)
pool
.
checkout
pid
=
fork
do
pool
=
ConnectionPool
.
new
(
role
)
pool
=
ConnectionPool
.
new
(
pool_config
)
conn
,
child
=
new_conn_in_thread
(
pool
)
child
.
terminate
...
...
@@ -173,10 +173,10 @@ def test_reaper_does_not_reap_discarded_connection_pools
end
private
def
duplicated_
role
def
duplicated_
pool_config
old_config
=
ActiveRecord
::
Base
.
connection_pool
.
db_config
.
configuration_hash
db_config
=
ActiveRecord
::
DatabaseConfigurations
::
HashConfig
.
new
(
"arunit"
,
"primary"
,
old_config
.
dup
)
Role
.
new
(
"primary"
,
db_config
)
PoolConfig
.
new
(
"primary"
,
db_config
)
end
def
new_conn_in_thread
(
pool
)
...
...
activerecord/test/cases/unconnected_test.rb
浏览文件 @
74688afe
...
...
@@ -13,7 +13,7 @@ def setup
@specification
=
ActiveRecord
::
Base
.
remove_connection
# Clear out connection info from other pids (like a fork parent) too
ActiveRecord
::
ConnectionAdapters
::
Role
.
discard_pools!
ActiveRecord
::
ConnectionAdapters
::
PoolConfig
.
discard_pools!
end
teardown
do
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录