active_record_host_pool 1.0.2 → 1.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Readme.md +36 -0
- data/lib/active_record_host_pool/clear_query_cache_patch.rb +42 -0
- data/lib/active_record_host_pool/connection_adapter_mixin.rb +19 -12
- data/lib/active_record_host_pool/pool_proxy.rb +4 -155
- data/lib/active_record_host_pool/pool_proxy_6_1.rb +150 -0
- data/lib/active_record_host_pool/pool_proxy_legacy.rb +152 -0
- data/lib/active_record_host_pool/version.rb +1 -1
- data/test/database.yml +52 -21
- data/test/helper.rb +157 -43
- data/test/schema.rb +16 -9
- data/test/test_arhp.rb +56 -103
- metadata +29 -12
data/test/database.yml
CHANGED
@@ -1,76 +1,107 @@
|
|
1
1
|
<% mysql = URI(ENV['MYSQL_URL'] || 'mysql://root@127.0.0.1:3306') %>
|
2
|
-
|
2
|
+
# ARHP creates separate connection pools based on the pool key.
|
3
|
+
# The pool key is defined as:
|
4
|
+
# host / port / socket / username / replica
|
5
|
+
#
|
6
|
+
# Therefore two databases with identical host, port, socket, username, and replica status will share a connection pool.
|
7
|
+
# If any part (host, port, etc.) of the pool key differ, two databases will _not_ share a connection pool.
|
8
|
+
#
|
9
|
+
# Below, "test_pool_1..." and "test_pool_2..." have identical host, username, socket, and replica status but the port information differs.
|
10
|
+
# Here the yml configurations are reformatted as a table to give a visual example:
|
11
|
+
#
|
12
|
+
# |----------+----------------+----------------|
|
13
|
+
# | | test_pool_1 | test_pool_2 |
|
14
|
+
# |----------+----------------+----------------+
|
15
|
+
# | host | 127.0.0.1 | 127.0.0.1 |
|
16
|
+
# | port | | 3306 |
|
17
|
+
# | socket | | |
|
18
|
+
# | username | root | root |
|
19
|
+
# | replica | false | false |
|
20
|
+
# |----------+----------------+----------------|
|
21
|
+
#
|
22
|
+
# Note: The configuration items must be explicitly defined or will be blank in the pool key.
|
23
|
+
# Configurations with matching _implicit_ items but differing _explicit_ items will create separate pools.
|
24
|
+
# e.g. "test_pool_1" will default to port 3306 but because it is not explicitly defined it will not share a pool with test_pool_2
|
25
|
+
#
|
26
|
+
# ARHP will therefore create the following pool keys:
|
27
|
+
# test_pool_1 => 127.0.0.1///root/false
|
28
|
+
# test_pool_2 => 127.0.0.1/3306//root/false
|
29
|
+
|
30
|
+
test_pool_1_db_a:
|
3
31
|
adapter: mysql2
|
4
32
|
encoding: utf8
|
5
|
-
database:
|
33
|
+
database: arhp_test_db_a
|
6
34
|
username: <%= mysql.user %>
|
7
35
|
password: <%= mysql.password %>
|
8
36
|
host: <%= mysql.host %>
|
9
37
|
reconnect: true
|
10
38
|
|
11
39
|
# Mimic configurations as read by active_record_shards/ar_flexmaster
|
12
|
-
|
40
|
+
test_pool_1_db_a_replica:
|
13
41
|
adapter: mysql2
|
14
42
|
encoding: utf8
|
15
|
-
database:
|
43
|
+
database: arhp_test_db_a_replica
|
16
44
|
username: <%= mysql.user %>
|
17
45
|
password: <%= mysql.password %>
|
18
46
|
host: <%= mysql.host %>
|
19
47
|
reconnect: true
|
20
48
|
slave: true
|
21
49
|
|
22
|
-
|
50
|
+
test_pool_1_db_b:
|
23
51
|
adapter: mysql2
|
24
52
|
encoding: utf8
|
25
|
-
database:
|
53
|
+
database: arhp_test_db_b
|
26
54
|
username: <%= mysql.user %>
|
27
55
|
password: <%= mysql.password %>
|
28
56
|
host: <%= mysql.host %>
|
29
57
|
reconnect: true
|
30
58
|
|
31
|
-
|
59
|
+
test_pool_1_db_not_there:
|
32
60
|
adapter: mysql2
|
33
61
|
encoding: utf8
|
34
|
-
database:
|
62
|
+
database: arhp_test_db_not_there
|
35
63
|
username: <%= mysql.user %>
|
36
64
|
password: <%= mysql.password %>
|
37
65
|
host: <%= mysql.host %>
|
38
|
-
port: <%= mysql.port %>
|
39
66
|
reconnect: true
|
40
67
|
|
41
|
-
|
68
|
+
test_pool_2_db_d:
|
42
69
|
adapter: mysql2
|
43
70
|
encoding: utf8
|
44
|
-
database:
|
71
|
+
database: arhp_test_db_d
|
45
72
|
username: <%= mysql.user %>
|
46
73
|
password: <%= mysql.password %>
|
47
74
|
host: <%= mysql.host %>
|
48
75
|
port: <%= mysql.port %>
|
49
76
|
reconnect: true
|
50
77
|
|
51
|
-
|
78
|
+
test_pool_2_db_e:
|
52
79
|
adapter: mysql2
|
53
80
|
encoding: utf8
|
54
|
-
database:
|
55
|
-
username:
|
56
|
-
password:
|
81
|
+
database: arhp_test_db_e
|
82
|
+
username: <%= mysql.user %>
|
83
|
+
password: <%= mysql.password %>
|
57
84
|
host: <%= mysql.host %>
|
58
85
|
port: <%= mysql.port %>
|
59
86
|
reconnect: true
|
60
87
|
|
61
|
-
|
88
|
+
test_pool_3_db_e:
|
62
89
|
adapter: mysql2
|
63
90
|
encoding: utf8
|
64
|
-
database:
|
65
|
-
username:
|
66
|
-
password:
|
91
|
+
database: arhp_test_db_e
|
92
|
+
username: john-doe
|
93
|
+
password:
|
67
94
|
host: <%= mysql.host %>
|
95
|
+
port: <%= mysql.port %>
|
68
96
|
reconnect: true
|
69
97
|
|
70
|
-
|
98
|
+
# test_pool_1_db_c needs to be the last database defined in the file
|
99
|
+
# otherwise the test_models_with_matching_hosts_and_non_matching_databases_issue_exists_without_arhp_patch
|
100
|
+
# test fails
|
101
|
+
test_pool_1_db_c:
|
71
102
|
adapter: mysql2
|
72
103
|
encoding: utf8
|
73
|
-
database:
|
104
|
+
database: arhp_test_db_c
|
74
105
|
username: <%= mysql.user %>
|
75
106
|
password: <%= mysql.password %>
|
76
107
|
host: <%= mysql.host %>
|
data/test/helper.rb
CHANGED
@@ -5,15 +5,41 @@ require 'minitest/autorun'
|
|
5
5
|
|
6
6
|
require 'active_record_host_pool'
|
7
7
|
require 'logger'
|
8
|
-
require 'mocha/
|
8
|
+
require 'mocha/minitest'
|
9
9
|
require 'phenix'
|
10
10
|
|
11
|
-
RAILS_ENV = 'test'
|
11
|
+
ENV['RAILS_ENV'] = 'test'
|
12
|
+
ENV['LEGACY_CONNECTION_HANDLING'] = 'true' if ENV['LEGACY_CONNECTION_HANDLING'].nil?
|
12
13
|
|
13
|
-
|
14
|
+
if ActiveRecord.version >= Gem::Version.new('6.1')
|
15
|
+
ActiveRecord::Base.legacy_connection_handling = (ENV['LEGACY_CONNECTION_HANDLING'] == 'true')
|
16
|
+
end
|
17
|
+
|
18
|
+
RAILS_6_1_WITH_NON_LEGACY_CONNECTION_HANDLING =
|
19
|
+
ActiveRecord.version >= Gem::Version.new('6.1') && !ActiveRecord::Base.legacy_connection_handling
|
14
20
|
|
15
21
|
ActiveRecord::Base.logger = Logger.new(File.dirname(__FILE__) + '/test.log')
|
16
22
|
|
23
|
+
# BEGIN preventing_writes? patch
|
24
|
+
## Rails 6.1 by default does not allow writing to replica databases which prevents
|
25
|
+
## us from properly setting up the test databases. This patch is used in test/schema.rb
|
26
|
+
## to allow us to write to the replicas but only during migrations
|
27
|
+
module ActiveRecordHostPool
|
28
|
+
cattr_accessor :allowing_writes
|
29
|
+
module PreventWritesPatch
|
30
|
+
def preventing_writes?
|
31
|
+
return false if ActiveRecordHostPool.allowing_writes && replica?
|
32
|
+
|
33
|
+
super
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
if ActiveRecord.version >= Gem::Version.new('6.1')
|
39
|
+
ActiveRecord::ConnectionAdapters::AbstractAdapter.prepend ActiveRecordHostPool::PreventWritesPatch
|
40
|
+
end
|
41
|
+
# END preventing_writes? patch
|
42
|
+
|
17
43
|
Phenix.configure do |config|
|
18
44
|
config.skip_database = ->(name, conf) { name =~ /not_there/ || conf['username'] == 'john-doe' }
|
19
45
|
end
|
@@ -22,46 +48,121 @@ module ARHPTestSetup
|
|
22
48
|
private
|
23
49
|
|
24
50
|
def arhp_create_models
|
25
|
-
return if ARHPTestSetup.const_defined?('
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
51
|
+
return if ARHPTestSetup.const_defined?('Pool1DbA')
|
52
|
+
|
53
|
+
if RAILS_6_1_WITH_NON_LEGACY_CONNECTION_HANDLING
|
54
|
+
eval <<-RUBY
|
55
|
+
class AbstractPool1DbC < ActiveRecord::Base
|
56
|
+
self.abstract_class = true
|
57
|
+
connects_to database: { writing: :test_pool_1_db_c }
|
58
|
+
end
|
59
|
+
|
60
|
+
# The placement of the Pool1DbC class is important so that its
|
61
|
+
# connection will not be the most recent connection established
|
62
|
+
# for test_pool_1.
|
63
|
+
class Pool1DbC < AbstractPool1DbC
|
64
|
+
end
|
65
|
+
|
66
|
+
class AbstractPool1DbA < ActiveRecord::Base
|
67
|
+
self.abstract_class = true
|
68
|
+
connects_to database: { writing: :test_pool_1_db_a, reading: :test_pool_1_db_a_replica }
|
69
|
+
end
|
70
|
+
|
71
|
+
class Pool1DbA < AbstractPool1DbA
|
72
|
+
self.table_name = "tests"
|
73
|
+
end
|
74
|
+
|
75
|
+
class AbstractPool1DbB < ActiveRecord::Base
|
76
|
+
self.abstract_class = true
|
77
|
+
connects_to database: { writing: :test_pool_1_db_b }
|
78
|
+
end
|
79
|
+
|
80
|
+
class Pool1DbB < AbstractPool1DbB
|
81
|
+
self.table_name = "tests"
|
82
|
+
end
|
83
|
+
|
84
|
+
class AbstractPool2DbD < ActiveRecord::Base
|
85
|
+
self.abstract_class = true
|
86
|
+
connects_to database: { writing: :test_pool_2_db_d }
|
87
|
+
end
|
88
|
+
|
89
|
+
class Pool2DbD < AbstractPool2DbD
|
90
|
+
self.table_name = "tests"
|
91
|
+
end
|
92
|
+
|
93
|
+
class AbstractPool2DbE < ActiveRecord::Base
|
94
|
+
self.abstract_class = true
|
95
|
+
connects_to database: { writing: :test_pool_2_db_e }
|
96
|
+
end
|
97
|
+
|
98
|
+
class Pool2DbE < AbstractPool2DbE
|
99
|
+
self.table_name = "tests"
|
100
|
+
end
|
101
|
+
|
102
|
+
class AbstractPool3DbE < ActiveRecord::Base
|
103
|
+
self.abstract_class = true
|
104
|
+
connects_to database: { writing: :test_pool_3_db_e }
|
105
|
+
end
|
106
|
+
|
107
|
+
class Pool3DbE < AbstractPool3DbE
|
108
|
+
self.table_name = "tests"
|
109
|
+
end
|
110
|
+
|
111
|
+
# Test ARHP with Rails 6.1+ horizontal sharding functionality
|
112
|
+
class AbstractShardedModel < ActiveRecord::Base
|
113
|
+
self.abstract_class = true
|
114
|
+
connects_to shards: {
|
115
|
+
default: { writing: :test_pool_1_db_shard_a },
|
116
|
+
shard_b: { writing: :test_pool_1_db_shard_b, reading: :test_pool_1_db_shard_b_replica },
|
117
|
+
shard_c: { writing: :test_pool_1_db_shard_c, reading: :test_pool_1_db_shard_c_replica },
|
118
|
+
shard_d: { writing: :test_pool_2_db_shard_d, reading: :test_pool_2_db_shard_d_replica }
|
119
|
+
}
|
120
|
+
end
|
121
|
+
|
122
|
+
class ShardedModel < AbstractShardedModel
|
123
|
+
self.table_name = "tests"
|
124
|
+
end
|
125
|
+
RUBY
|
126
|
+
else
|
127
|
+
eval <<-RUBY
|
128
|
+
# The placement of the Pool1DbC class is important so that its
|
129
|
+
# connection will not be the most recent connection established
|
130
|
+
# for test_pool_1.
|
131
|
+
class Pool1DbC < ActiveRecord::Base
|
132
|
+
establish_connection(:test_pool_1_db_c)
|
133
|
+
end
|
134
|
+
|
135
|
+
class Pool1DbA < ActiveRecord::Base
|
136
|
+
self.table_name = "tests"
|
137
|
+
establish_connection(:test_pool_1_db_a)
|
138
|
+
end
|
139
|
+
|
140
|
+
class Pool1DbAReplica < ActiveRecord::Base
|
141
|
+
self.table_name = "tests"
|
142
|
+
establish_connection(:test_pool_1_db_a_replica)
|
143
|
+
end
|
144
|
+
|
145
|
+
class Pool1DbB < ActiveRecord::Base
|
146
|
+
self.table_name = "tests"
|
147
|
+
establish_connection(:test_pool_1_db_b)
|
148
|
+
end
|
149
|
+
|
150
|
+
class Pool2DbD < ActiveRecord::Base
|
151
|
+
self.table_name = "tests"
|
152
|
+
establish_connection(:test_pool_2_db_d)
|
153
|
+
end
|
154
|
+
|
155
|
+
class Pool2DbE < ActiveRecord::Base
|
156
|
+
self.table_name = "tests"
|
157
|
+
establish_connection(:test_pool_2_db_e)
|
158
|
+
end
|
159
|
+
|
160
|
+
class Pool3DbE < ActiveRecord::Base
|
161
|
+
self.table_name = "tests"
|
162
|
+
establish_connection(:test_pool_3_db_e)
|
163
|
+
end
|
164
|
+
RUBY
|
165
|
+
end
|
65
166
|
end
|
66
167
|
|
67
168
|
def current_database(klass)
|
@@ -78,4 +179,17 @@ module ARHPTestSetup
|
|
78
179
|
ensure
|
79
180
|
mod.define_method(method_name, method_body)
|
80
181
|
end
|
182
|
+
|
183
|
+
def simulate_rails_app_active_record_railties
|
184
|
+
if ActiveRecord.version >= Gem::Version.new('6.0') && !RAILS_6_1_WITH_NON_LEGACY_CONNECTION_HANDLING
|
185
|
+
# Necessary for testing ActiveRecord 6.0 which uses the connection
|
186
|
+
# handlers when clearing query caches across all handlers when
|
187
|
+
# an operation that dirties the cache is involved (e.g. create/insert,
|
188
|
+
# update, delete/destroy, truncate, etc.)
|
189
|
+
# In Rails 6.1 this is only present when legacy_connection_handling=true
|
190
|
+
ActiveRecord::Base.connection_handlers = {
|
191
|
+
ActiveRecord::Base.writing_role => ActiveRecord::Base.default_connection_handler
|
192
|
+
}
|
193
|
+
end
|
194
|
+
end
|
81
195
|
end
|
data/test/schema.rb
CHANGED
@@ -1,16 +1,23 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require_relative 'helper'
|
4
|
-
ActiveRecord::Schema.define(version: 1) do
|
5
|
-
create_table 'tests', force: true do |t|
|
6
|
-
t.string 'val'
|
7
|
-
end
|
8
4
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
5
|
+
begin
|
6
|
+
ActiveRecordHostPool.allowing_writes = true
|
7
|
+
|
8
|
+
ActiveRecord::Schema.define(version: 1) do
|
9
|
+
create_table 'tests', force: true do |t|
|
10
|
+
t.string 'val'
|
11
|
+
end
|
12
|
+
|
13
|
+
# Add a table only the shard database will have. Conditional
|
14
|
+
# exists since Phenix loads the schema file for every database.
|
15
|
+
if ActiveRecord::Base.connection.current_database == 'arhp_test_db_c'
|
16
|
+
create_table 'pool1_db_cs' do |t|
|
17
|
+
t.string 'name'
|
18
|
+
end
|
14
19
|
end
|
15
20
|
end
|
21
|
+
ensure
|
22
|
+
ActiveRecordHostPool.allowing_writes = false
|
16
23
|
end
|
data/test/test_arhp.rb
CHANGED
@@ -5,11 +5,17 @@ require_relative 'helper'
|
|
5
5
|
class ActiveRecordHostPoolTest < Minitest::Test
|
6
6
|
include ARHPTestSetup
|
7
7
|
def setup
|
8
|
-
|
8
|
+
if RAILS_6_1_WITH_NON_LEGACY_CONNECTION_HANDLING
|
9
|
+
Phenix.rise! config_path: 'test/three_tier_database.yml'
|
10
|
+
else
|
11
|
+
Phenix.rise!
|
12
|
+
end
|
9
13
|
arhp_create_models
|
10
14
|
end
|
11
15
|
|
12
16
|
def teardown
|
17
|
+
ActiveRecord::Base.connection.disconnect!
|
18
|
+
ActiveRecordHostPool::PoolProxy.class_variable_set(:@@_connection_pools, {})
|
13
19
|
Phenix.burn!
|
14
20
|
end
|
15
21
|
|
@@ -30,110 +36,80 @@ class ActiveRecordHostPoolTest < Minitest::Test
|
|
30
36
|
ActiveRecord::Base.connection_handler.clear_all_connections!
|
31
37
|
end
|
32
38
|
|
33
|
-
def
|
34
|
-
assert_equal(
|
35
|
-
assert_equal(
|
36
|
-
end
|
37
|
-
|
38
|
-
def test_models_without_matching_hosts_should_not_share_a_connection
|
39
|
-
refute_equal(Test1.connection.raw_connection, Test4.connection.raw_connection)
|
39
|
+
def test_models_with_matching_hosts_ports_sockets_usernames_and_replica_status_should_share_a_connection
|
40
|
+
assert_equal(Pool1DbA.connection.raw_connection, Pool1DbB.connection.raw_connection)
|
41
|
+
assert_equal(Pool2DbD.connection.raw_connection, Pool2DbE.connection.raw_connection)
|
40
42
|
end
|
41
43
|
|
42
|
-
def
|
43
|
-
refute_equal(
|
44
|
+
def test_models_with_different_ports_should_not_share_a_connection
|
45
|
+
refute_equal(Pool1DbA.connection.raw_connection, Pool2DbD.connection.raw_connection)
|
44
46
|
end
|
45
47
|
|
46
|
-
def
|
47
|
-
refute_equal(
|
48
|
+
def test_models_with_different_usernames_should_not_share_a_connection
|
49
|
+
refute_equal(Pool2DbE.connection.raw_connection, Pool3DbE.connection.raw_connection)
|
48
50
|
end
|
49
51
|
|
50
52
|
def test_should_select_on_correct_database
|
51
|
-
|
52
|
-
|
53
|
+
Pool1DbA.connection.send(:select_all, 'select 1')
|
54
|
+
assert_equal 'arhp_test_db_a', current_database(Pool1DbA)
|
53
55
|
|
54
|
-
|
55
|
-
|
56
|
-
end
|
56
|
+
Pool2DbD.connection.send(:select_all, 'select 1')
|
57
|
+
assert_equal 'arhp_test_db_d', current_database(Pool2DbD)
|
57
58
|
|
58
|
-
|
59
|
-
|
60
|
-
assert_equal(Test1.connection.raw_connection, Test1Shard.connection.raw_connection)
|
59
|
+
Pool3DbE.connection.send(:select_all, 'select 1')
|
60
|
+
assert_equal 'arhp_test_db_e', current_database(Pool3DbE)
|
61
61
|
end
|
62
62
|
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
# Remove patch that fixes an issue in Rails 6+ to ensure it still
|
68
|
-
# exists. If this begins to fail then it may mean that Rails has fixed
|
69
|
-
# the issue so that it no longer occurs.
|
70
|
-
without_module_patch(ActiveRecordHostPool::ClearQueryCachePatch, :clear_query_caches_for_current_thread) do
|
71
|
-
exception = assert_raises(ActiveRecord::StatementInvalid) do
|
72
|
-
ActiveRecord::Base.cache { Test1Shard.create! }
|
73
|
-
end
|
74
|
-
|
75
|
-
assert_equal("Mysql2::Error: Table 'arhp_test_2.test1_shards' doesn't exist", exception.message)
|
76
|
-
end
|
77
|
-
end
|
63
|
+
def test_should_insert_on_correct_database
|
64
|
+
Pool1DbA.connection.send(:insert, "insert into tests values(NULL, 'foo')")
|
65
|
+
assert_equal 'arhp_test_db_a', current_database(Pool1DbA)
|
78
66
|
|
79
|
-
|
80
|
-
|
67
|
+
Pool2DbD.connection.send(:insert, "insert into tests values(NULL, 'foo')")
|
68
|
+
assert_equal 'arhp_test_db_d', current_database(Pool2DbD)
|
81
69
|
|
82
|
-
|
83
|
-
|
84
|
-
# handlers which can cause the database to change.
|
85
|
-
# See ActiveRecordHostPool::ClearQueryCachePatch
|
86
|
-
ActiveRecord::Base.cache { Test1Shard.create! }
|
87
|
-
end
|
70
|
+
Pool3DbE.connection.send(:insert, "insert into tests values(NULL, 'foo')")
|
71
|
+
assert_equal 'arhp_test_db_e', current_database(Pool3DbE)
|
88
72
|
end
|
89
73
|
|
90
74
|
def test_connection_returns_a_proxy
|
91
|
-
assert_kind_of ActiveRecordHostPool::ConnectionProxy,
|
75
|
+
assert_kind_of ActiveRecordHostPool::ConnectionProxy, Pool1DbA.connection
|
92
76
|
end
|
93
77
|
|
94
78
|
def test_connection_proxy_handles_private_methods
|
95
79
|
# Relies on connection.class returning the real class
|
96
|
-
|
80
|
+
Pool1DbA.connection.class.class_eval do
|
97
81
|
private
|
98
82
|
|
99
83
|
def test_private_method
|
100
84
|
true
|
101
85
|
end
|
102
86
|
end
|
103
|
-
assert
|
104
|
-
refute
|
105
|
-
assert_includes(
|
106
|
-
assert_equal true,
|
107
|
-
end
|
108
|
-
|
109
|
-
def test_should_not_share_a_query_cache
|
110
|
-
Test1.create(val: 'foo')
|
111
|
-
Test2.create(val: 'foobar')
|
112
|
-
Test1.connection.cache do
|
113
|
-
refute_equal Test1.first.val, Test2.first.val
|
114
|
-
end
|
87
|
+
assert Pool1DbA.connection.respond_to?(:test_private_method, true)
|
88
|
+
refute Pool1DbA.connection.respond_to?(:test_private_method)
|
89
|
+
assert_includes(Pool1DbA.connection.private_methods, :test_private_method)
|
90
|
+
assert_equal true, Pool1DbA.connection.send(:test_private_method)
|
115
91
|
end
|
116
92
|
|
117
93
|
def test_object_creation
|
118
|
-
|
119
|
-
assert_equal('
|
94
|
+
Pool1DbA.create(val: 'foo')
|
95
|
+
assert_equal('arhp_test_db_a', current_database(Pool1DbA))
|
120
96
|
|
121
|
-
|
122
|
-
assert_equal('
|
123
|
-
assert_equal('
|
97
|
+
Pool2DbD.create(val: 'bar')
|
98
|
+
assert_equal('arhp_test_db_a', current_database(Pool1DbA))
|
99
|
+
assert_equal('arhp_test_db_d', current_database(Pool2DbD))
|
124
100
|
|
125
|
-
|
126
|
-
assert_equal('
|
127
|
-
assert
|
128
|
-
refute
|
101
|
+
Pool1DbB.create!(val: 'bar_distinct')
|
102
|
+
assert_equal('arhp_test_db_b', current_database(Pool1DbB))
|
103
|
+
assert Pool1DbB.find_by_val('bar_distinct')
|
104
|
+
refute Pool1DbA.find_by_val('bar_distinct')
|
129
105
|
end
|
130
106
|
|
131
107
|
def test_disconnect
|
132
|
-
|
133
|
-
unproxied =
|
134
|
-
|
135
|
-
|
136
|
-
assert(unproxied !=
|
108
|
+
Pool1DbA.create(val: 'foo')
|
109
|
+
unproxied = Pool1DbA.connection.unproxied
|
110
|
+
Pool1DbA.connection_handler.clear_all_connections!
|
111
|
+
Pool1DbA.create(val: 'foo')
|
112
|
+
assert(unproxied != Pool1DbA.connection.unproxied)
|
137
113
|
end
|
138
114
|
|
139
115
|
def test_checkout
|
@@ -145,7 +121,7 @@ class ActiveRecordHostPoolTest < Minitest::Test
|
|
145
121
|
end
|
146
122
|
|
147
123
|
def test_no_switch_when_creating_db
|
148
|
-
conn =
|
124
|
+
conn = Pool1DbA.connection
|
149
125
|
conn.expects(:execute_without_switching)
|
150
126
|
conn.expects(:_switch_connection).never
|
151
127
|
assert conn._host_pool_current_database
|
@@ -153,7 +129,7 @@ class ActiveRecordHostPoolTest < Minitest::Test
|
|
153
129
|
end
|
154
130
|
|
155
131
|
def test_no_switch_when_dropping_db
|
156
|
-
conn =
|
132
|
+
conn = Pool1DbA.connection
|
157
133
|
conn.expects(:execute_without_switching)
|
158
134
|
conn.expects(:_switch_connection).never
|
159
135
|
assert conn._host_pool_current_database
|
@@ -163,17 +139,17 @@ class ActiveRecordHostPoolTest < Minitest::Test
|
|
163
139
|
def test_underlying_assumption_about_test_db
|
164
140
|
debug_me = false
|
165
141
|
# ensure connection
|
166
|
-
|
142
|
+
Pool1DbA.first
|
167
143
|
|
168
144
|
# which is the "default" DB to connect to?
|
169
|
-
first_db =
|
145
|
+
first_db = Pool1DbA.connection.unproxied.instance_variable_get(:@_cached_current_database)
|
170
146
|
puts "\nOk, we started on #{first_db}" if debug_me
|
171
147
|
|
172
148
|
switch_to_klass = case first_db
|
173
|
-
when '
|
174
|
-
|
175
|
-
when '
|
176
|
-
|
149
|
+
when 'arhp_test_db_b'
|
150
|
+
Pool1DbA
|
151
|
+
when 'arhp_test_db_a'
|
152
|
+
Pool1DbB
|
177
153
|
else
|
178
154
|
raise "Expected a database name, got #{first_db.inspect}"
|
179
155
|
end
|
@@ -188,7 +164,7 @@ class ActiveRecordHostPoolTest < Minitest::Test
|
|
188
164
|
|
189
165
|
# now, disable our auto-switching and trigger a mysql reconnect
|
190
166
|
switch_to_klass.connection.unproxied.stubs(:_switch_connection).returns(true)
|
191
|
-
|
167
|
+
Pool2DbD.connection.execute("KILL #{thread_id}")
|
192
168
|
|
193
169
|
# and finally, did mysql reconnect correctly?
|
194
170
|
puts "\nAnd now we end up on #{current_database(switch_to_klass)}" if debug_me
|
@@ -201,27 +177,4 @@ class ActiveRecordHostPoolTest < Minitest::Test
|
|
201
177
|
pool.expects(:checkin).with(conn)
|
202
178
|
pool.release_connection
|
203
179
|
end
|
204
|
-
|
205
|
-
private
|
206
|
-
|
207
|
-
def assert_action_uses_correct_database(action, sql)
|
208
|
-
(1..4).each do |i|
|
209
|
-
klass = ARHPTestSetup.const_get("Test#{i}")
|
210
|
-
desired_db = "arhp_test_#{i}"
|
211
|
-
klass.connection.send(action, sql)
|
212
|
-
assert_equal desired_db, current_database(klass)
|
213
|
-
end
|
214
|
-
end
|
215
|
-
|
216
|
-
def simulate_rails_app_active_record_railties
|
217
|
-
if ActiveRecord.version >= Gem::Version.new('6.0')
|
218
|
-
# Necessary for testing ActiveRecord 6.0 which uses the connection
|
219
|
-
# handlers when clearing query caches across all handlers when
|
220
|
-
# an operation that dirties the cache is involved (e.g. create/insert,
|
221
|
-
# update, delete/destroy, truncate, etc.)
|
222
|
-
ActiveRecord::Base.connection_handlers = {
|
223
|
-
ActiveRecord::Base.writing_role => ActiveRecord::Base.default_connection_handler
|
224
|
-
}
|
225
|
-
end
|
226
|
-
end
|
227
180
|
end
|