active_record_host_pool 0.10.0 → 0.10.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/lib/active_record_host_pool.rb +1 -0
- data/lib/active_record_host_pool/connection_adapter_mixin.rb +24 -19
- data/lib/active_record_host_pool/connection_proxy.rb +3 -3
- data/lib/active_record_host_pool/pool_proxy.rb +13 -14
- data/lib/active_record_host_pool/version.rb +2 -1
- data/test/helper.rb +5 -4
- data/test/schema.rb +5 -3
- data/test/test_arhp.rb +49 -31
- metadata +19 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 336ed17f3718db418f1f757a17a81fbb0e24da41
|
4
|
+
data.tar.gz: a3902cee8a77566286c728feb6511d397a80e5a6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: def4a6ebe3b0069c2de4374c46b33c93d739511b0b8c893cc9e12797dc6fc94e449b9971b2214053c29e9572fc993ffdccec49a440266ee974d7976ec7adbc63
|
7
|
+
data.tar.gz: 520d09bd7360556db30a3a0289acc3b5defca029919998d521d9160cc00ada03029f7b8aab9ab209594cad77e70048e60417a5382b9588609da7964b6e0f42b9
|
@@ -1,4 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
['mysql_adapter', 'mysql2_adapter'].each do |adapter|
|
3
4
|
begin
|
4
5
|
require "active_record/connection_adapters/#{adapter}"
|
@@ -31,29 +32,30 @@ module ActiveRecordHostPool
|
|
31
32
|
end
|
32
33
|
end
|
33
34
|
|
35
|
+
def initialize(*)
|
36
|
+
@_cached_current_database = nil
|
37
|
+
super
|
38
|
+
end
|
39
|
+
|
34
40
|
def execute_with_switching(*args)
|
35
|
-
if _host_pool_current_database && !
|
41
|
+
if _host_pool_current_database && !_no_switch
|
36
42
|
_switch_connection
|
37
43
|
end
|
38
44
|
execute_without_switching(*args)
|
39
45
|
end
|
40
46
|
|
41
47
|
def drop_database_with_no_switching(*args)
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
@_no_switch = false
|
47
|
-
end
|
48
|
+
self._no_switch = true
|
49
|
+
drop_database_without_no_switching(*args)
|
50
|
+
ensure
|
51
|
+
self._no_switch = false
|
48
52
|
end
|
49
53
|
|
50
54
|
def create_database_with_no_switching(*args)
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
@_no_switch = false
|
56
|
-
end
|
55
|
+
self._no_switch = true
|
56
|
+
create_database_without_no_switching(*args)
|
57
|
+
ensure
|
58
|
+
self._no_switch = false
|
57
59
|
end
|
58
60
|
|
59
61
|
def disconnect_with_host_pooling!
|
@@ -64,8 +66,14 @@ module ActiveRecordHostPool
|
|
64
66
|
|
65
67
|
private
|
66
68
|
|
69
|
+
attr_accessor :_no_switch
|
70
|
+
|
67
71
|
def _switch_connection
|
68
|
-
if _host_pool_current_database &&
|
72
|
+
if _host_pool_current_database &&
|
73
|
+
(
|
74
|
+
(_host_pool_current_database != @_cached_current_database) ||
|
75
|
+
@connection.object_id != @_cached_connection_object_id
|
76
|
+
)
|
69
77
|
log("select_db #{_host_pool_current_database}", "SQL") do
|
70
78
|
clear_cache! if respond_to?(:clear_cache!)
|
71
79
|
raw_connection.select_db(_host_pool_current_database)
|
@@ -85,7 +93,6 @@ end
|
|
85
93
|
module ActiveRecord
|
86
94
|
module ConnectionAdapters
|
87
95
|
class ConnectionHandler
|
88
|
-
|
89
96
|
if ActiveRecord::VERSION::MAJOR == 5
|
90
97
|
if ActiveRecord::VERSION::MINOR == 0
|
91
98
|
def establish_connection(spec)
|
@@ -104,11 +111,11 @@ module ActiveRecord
|
|
104
111
|
|
105
112
|
def establish_connection(owner, spec)
|
106
113
|
@class_to_pool.clear
|
107
|
-
raise
|
114
|
+
raise "Anonymous class is not allowed." unless owner.name
|
108
115
|
owner_to_pool[owner.name] = ActiveRecordHostPool::PoolProxy.new(spec)
|
109
116
|
end
|
110
117
|
|
111
|
-
elsif ActiveRecord::VERSION::MAJOR == 3
|
118
|
+
elsif ActiveRecord::VERSION::MAJOR == 3
|
112
119
|
|
113
120
|
def establish_connection(owner, spec)
|
114
121
|
@connection_pools[spec] ||= ActiveRecordHostPool::PoolProxy.new(spec)
|
@@ -120,9 +127,7 @@ module ActiveRecord
|
|
120
127
|
def establish_connection(owner, spec)
|
121
128
|
@connection_pools[owner] = ActiveRecordHostPool::PoolProxy.new(spec)
|
122
129
|
end
|
123
|
-
|
124
130
|
end
|
125
|
-
|
126
131
|
end
|
127
132
|
end
|
128
133
|
end
|
@@ -1,4 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
require 'delegate'
|
3
4
|
|
4
5
|
# the ConnectionProxy sits between user-code and a real connection and says "I expect to be on this database"
|
@@ -38,7 +39,7 @@ module ActiveRecordHostPool
|
|
38
39
|
__getobj__.respond_to?(m, include_private)
|
39
40
|
end
|
40
41
|
|
41
|
-
def private_methods(all=true)
|
42
|
+
def private_methods(all = true)
|
42
43
|
__getobj__.private_methods(all) | super
|
43
44
|
end
|
44
45
|
|
@@ -51,10 +52,9 @@ module ActiveRecordHostPool
|
|
51
52
|
end
|
52
53
|
|
53
54
|
private
|
55
|
+
|
54
56
|
def select(*args)
|
55
57
|
@cx.__send__(:select, *args)
|
56
58
|
end
|
57
59
|
end
|
58
60
|
end
|
59
|
-
|
60
|
-
|
@@ -1,4 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
require 'delegate'
|
3
4
|
require 'active_record'
|
4
5
|
require 'active_record_host_pool/connection_adapter_mixin'
|
@@ -34,15 +35,13 @@ module ActiveRecordHostPool
|
|
34
35
|
end
|
35
36
|
|
36
37
|
def connection(*args)
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
_connection_pools.delete(_pool_key)
|
43
|
-
end
|
44
|
-
Kernel.raise(e)
|
38
|
+
real_connection = _connection_pool.connection(*args)
|
39
|
+
_connection_proxy_for(real_connection, @config[:database])
|
40
|
+
rescue Exception => e
|
41
|
+
if rescuable_errors.any? { |r| e.is_a?(r) }
|
42
|
+
_connection_pools.delete(_pool_key)
|
45
43
|
end
|
44
|
+
Kernel.raise(e)
|
46
45
|
end
|
47
46
|
|
48
47
|
# by the time we are patched into ActiveRecord, the current thread has already established
|
@@ -59,9 +58,9 @@ module ActiveRecordHostPool
|
|
59
58
|
|
60
59
|
def with_connection
|
61
60
|
cx = checkout
|
62
|
-
|
63
|
-
|
64
|
-
|
61
|
+
yield cx
|
62
|
+
ensure
|
63
|
+
checkin cx
|
65
64
|
end
|
66
65
|
|
67
66
|
def disconnect!
|
@@ -83,7 +82,8 @@ module ActiveRecordHostPool
|
|
83
82
|
_clear_connection_proxy_cache
|
84
83
|
end
|
85
84
|
|
86
|
-
|
85
|
+
private
|
86
|
+
|
87
87
|
def rescuable_errors
|
88
88
|
@rescuable_errors ||= begin
|
89
89
|
e = []
|
@@ -108,7 +108,7 @@ module ActiveRecordHostPool
|
|
108
108
|
@_pool_key ||= "#{@config[:host]}/#{@config[:port]}/#{@config[:socket]}/#{@config[:username]}/#{@config[:slave] && 'slave'}"
|
109
109
|
end
|
110
110
|
|
111
|
-
def _connection_pool(auto_create=true)
|
111
|
+
def _connection_pool(auto_create = true)
|
112
112
|
pool = _connection_pools[_pool_key]
|
113
113
|
if pool.nil? && auto_create
|
114
114
|
pool = _connection_pools[_pool_key] = ActiveRecord::ConnectionAdapters::ConnectionPool.new(@spec)
|
@@ -132,4 +132,3 @@ module ActiveRecordHostPool
|
|
132
132
|
end
|
133
133
|
end
|
134
134
|
end
|
135
|
-
|
data/test/helper.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
require 'bundler/setup'
|
3
4
|
require 'minitest/autorun'
|
4
5
|
|
@@ -7,11 +8,11 @@ require 'logger'
|
|
7
8
|
require 'mocha/setup'
|
8
9
|
require 'phenix'
|
9
10
|
|
10
|
-
RAILS_ENV =
|
11
|
+
RAILS_ENV = 'test'
|
11
12
|
|
12
13
|
Minitest::Test = MiniTest::Unit::TestCase unless defined?(::Minitest::Test)
|
13
14
|
|
14
|
-
ActiveRecord::Base.logger = Logger.new(File.dirname(__FILE__) +
|
15
|
+
ActiveRecord::Base.logger = Logger.new(File.dirname(__FILE__) + '/test.log')
|
15
16
|
|
16
17
|
Phenix.configure do |config|
|
17
18
|
config.skip_database = ->(name, conf) { name =~ /not_there/ || conf['username'] == 'travis' }
|
@@ -21,7 +22,7 @@ module ARHPTestSetup
|
|
21
22
|
private
|
22
23
|
|
23
24
|
def arhp_create_models
|
24
|
-
return if Object.const_defined?(
|
25
|
+
return if Object.const_defined?('Test1')
|
25
26
|
eval <<-EOL
|
26
27
|
class Test1 < ActiveRecord::Base
|
27
28
|
self.table_name = "tests"
|
@@ -56,6 +57,6 @@ module ARHPTestSetup
|
|
56
57
|
end
|
57
58
|
|
58
59
|
def current_database(klass)
|
59
|
-
klass.connection.select_value(
|
60
|
+
klass.connection.select_value('select DATABASE()')
|
60
61
|
end
|
61
62
|
end
|
data/test/schema.rb
CHANGED
data/test/test_arhp.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
require_relative 'helper'
|
3
4
|
|
4
5
|
class ActiveRecordHostPoolTest < Minitest::Test
|
@@ -13,32 +14,32 @@ class ActiveRecordHostPoolTest < Minitest::Test
|
|
13
14
|
end
|
14
15
|
|
15
16
|
def test_models_with_matching_hosts_should_share_a_connection
|
16
|
-
|
17
|
-
|
17
|
+
assert_equal(Test1.connection.raw_connection, Test2.connection.raw_connection)
|
18
|
+
assert_equal(Test3.connection.raw_connection, Test4.connection.raw_connection)
|
18
19
|
end
|
19
20
|
|
20
21
|
def test_models_without_matching_hosts_should_not_share_a_connection
|
21
|
-
|
22
|
+
refute_equal(Test1.connection.raw_connection, Test4.connection.raw_connection)
|
22
23
|
end
|
23
24
|
|
24
25
|
def test_models_without_matching_usernames_should_not_share_a_connection
|
25
|
-
|
26
|
+
refute_equal(Test4.connection.raw_connection, Test5.connection.raw_connection)
|
26
27
|
end
|
27
28
|
|
28
29
|
def test_models_without_match_slave_status_should_not_share_a_connection
|
29
|
-
|
30
|
+
refute_equal(Test1.connection.raw_connection, Test1Slave.connection.raw_connection)
|
30
31
|
end
|
31
32
|
|
32
33
|
def test_should_select_on_correct_database
|
33
|
-
|
34
|
+
assert_action_uses_correct_database(:select_all, 'select 1')
|
34
35
|
end
|
35
36
|
|
36
37
|
def test_should_insert_on_correct_database
|
37
|
-
|
38
|
+
assert_action_uses_correct_database(:insert, "insert into tests values(NULL, 'foo')")
|
38
39
|
end
|
39
40
|
|
40
41
|
def test_connection_returns_a_proxy
|
41
|
-
|
42
|
+
assert_kind_of ActiveRecordHostPool::ConnectionProxy, Test1.connection
|
42
43
|
end
|
43
44
|
|
44
45
|
def test_connection_proxy_handles_private_methods
|
@@ -52,47 +53,62 @@ class ActiveRecordHostPoolTest < Minitest::Test
|
|
52
53
|
assert Test1.connection.respond_to?(:test_private_method, true)
|
53
54
|
refute Test1.connection.respond_to?(:test_private_method)
|
54
55
|
assert_includes(Test1.connection.private_methods, :test_private_method)
|
55
|
-
|
56
|
+
assert_equal true, Test1.connection.send(:test_private_method)
|
56
57
|
end
|
57
58
|
|
58
59
|
def test_should_not_share_a_query_cache
|
59
|
-
Test1.create(:
|
60
|
-
Test2.create(:
|
60
|
+
Test1.create(val: 'foo')
|
61
|
+
Test2.create(val: 'foobar')
|
61
62
|
Test1.connection.cache do
|
62
|
-
|
63
|
+
refute_equal Test1.first.val, Test2.first.val
|
63
64
|
end
|
64
65
|
end
|
65
66
|
|
66
67
|
def test_object_creation
|
67
|
-
Test1.create(:
|
68
|
-
assert_equal(
|
68
|
+
Test1.create(val: 'foo')
|
69
|
+
assert_equal('arhp_test_1', current_database(Test1))
|
69
70
|
|
70
|
-
Test3.create(:
|
71
|
-
assert_equal(
|
72
|
-
assert_equal(
|
71
|
+
Test3.create(val: 'bar')
|
72
|
+
assert_equal('arhp_test_1', current_database(Test1))
|
73
|
+
assert_equal('arhp_test_3', current_database(Test3))
|
73
74
|
|
74
|
-
Test2.create!(:
|
75
|
-
assert_equal(
|
75
|
+
Test2.create!(val: 'bar_distinct')
|
76
|
+
assert_equal('arhp_test_2', current_database(Test2))
|
76
77
|
assert Test2.find_by_val('bar_distinct')
|
77
|
-
|
78
|
+
refute Test1.find_by_val('bar_distinct')
|
78
79
|
end
|
79
80
|
|
80
81
|
def test_disconnect
|
81
|
-
Test1.create(:
|
82
|
+
Test1.create(val: 'foo')
|
82
83
|
unproxied = Test1.connection.unproxied
|
83
84
|
Test1.connection_handler.clear_all_connections!
|
84
|
-
Test1.create(:
|
85
|
+
Test1.create(val: 'foo')
|
85
86
|
assert(unproxied != Test1.connection.unproxied)
|
86
87
|
end
|
87
88
|
|
88
89
|
def test_checkout
|
89
90
|
connection = ActiveRecord::Base.connection_pool.checkout
|
90
|
-
|
91
|
+
assert_kind_of(ActiveRecordHostPool::ConnectionProxy, connection)
|
91
92
|
ActiveRecord::Base.connection_pool.checkin(connection)
|
92
93
|
c2 = ActiveRecord::Base.connection_pool.checkout
|
93
94
|
assert(c2 == connection)
|
94
95
|
end
|
95
96
|
|
97
|
+
def test_no_switch_when_creating_db
|
98
|
+
conn = Test1.connection
|
99
|
+
conn.expects(:execute_without_switching)
|
100
|
+
conn.expects(:_switch_connection).never
|
101
|
+
assert conn._host_pool_current_database
|
102
|
+
conn.create_database(:some_args)
|
103
|
+
end
|
104
|
+
|
105
|
+
def test_no_switch_when_dropping_db
|
106
|
+
conn = Test1.connection
|
107
|
+
conn.expects(:execute_without_switching)
|
108
|
+
conn.expects(:_switch_connection).never
|
109
|
+
assert conn._host_pool_current_database
|
110
|
+
conn.drop_database(:some_args)
|
111
|
+
end
|
96
112
|
|
97
113
|
def test_underlying_assumption_about_test_db
|
98
114
|
debug_me = false
|
@@ -104,10 +120,12 @@ class ActiveRecordHostPoolTest < Minitest::Test
|
|
104
120
|
puts "\nOk, we started on #{first_db}" if debug_me
|
105
121
|
|
106
122
|
switch_to_klass = case first_db
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
123
|
+
when 'arhp_test_2'
|
124
|
+
Test1
|
125
|
+
when 'arhp_test_1'
|
126
|
+
Test2
|
127
|
+
else
|
128
|
+
raise "Expected a database name, got #{first_db.inspect}"
|
111
129
|
end
|
112
130
|
expected_database = switch_to_klass.connection.instance_variable_get(:@database)
|
113
131
|
|
@@ -116,7 +134,7 @@ class ActiveRecordHostPoolTest < Minitest::Test
|
|
116
134
|
puts "\nAnd now we're on #{current_database(switch_to_klass)}" if debug_me
|
117
135
|
|
118
136
|
# get the current thread id so we can shoot ourselves in the head
|
119
|
-
thread_id = switch_to_klass.connection.select_value(
|
137
|
+
thread_id = switch_to_klass.connection.select_value('select @@pseudo_thread_id')
|
120
138
|
|
121
139
|
# now, disable our auto-switching and trigger a mysql reconnect
|
122
140
|
switch_to_klass.connection.unproxied.stubs(:_switch_connection).returns(true)
|
@@ -129,12 +147,12 @@ class ActiveRecordHostPoolTest < Minitest::Test
|
|
129
147
|
|
130
148
|
private
|
131
149
|
|
132
|
-
def
|
133
|
-
(1..4).each
|
150
|
+
def assert_action_uses_correct_database(action, sql)
|
151
|
+
(1..4).each do |i|
|
134
152
|
klass = eval "Test#{i}"
|
135
153
|
desired_db = "arhp_test_#{i}"
|
136
154
|
klass.connection.send(action, sql)
|
137
155
|
assert_equal desired_db, current_database(klass)
|
138
|
-
|
156
|
+
end
|
139
157
|
end
|
140
158
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: active_record_host_pool
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.10.
|
4
|
+
version: 0.10.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ben Osheroff
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-
|
11
|
+
date: 2017-04-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|
@@ -64,14 +64,14 @@ dependencies:
|
|
64
64
|
requirements:
|
65
65
|
- - ">="
|
66
66
|
- !ruby/object:Gem::Version
|
67
|
-
version:
|
67
|
+
version: 12.0.0
|
68
68
|
type: :development
|
69
69
|
prerelease: false
|
70
70
|
version_requirements: !ruby/object:Gem::Requirement
|
71
71
|
requirements:
|
72
72
|
- - ">="
|
73
73
|
- !ruby/object:Gem::Version
|
74
|
-
version:
|
74
|
+
version: 12.0.0
|
75
75
|
- !ruby/object:Gem::Dependency
|
76
76
|
name: shoulda
|
77
77
|
requirement: !ruby/object:Gem::Requirement
|
@@ -128,6 +128,20 @@ dependencies:
|
|
128
128
|
- - ">="
|
129
129
|
- !ruby/object:Gem::Version
|
130
130
|
version: '0'
|
131
|
+
- !ruby/object:Gem::Dependency
|
132
|
+
name: rubocop
|
133
|
+
requirement: !ruby/object:Gem::Requirement
|
134
|
+
requirements:
|
135
|
+
- - ">="
|
136
|
+
- !ruby/object:Gem::Version
|
137
|
+
version: 0.48.0
|
138
|
+
type: :development
|
139
|
+
prerelease: false
|
140
|
+
version_requirements: !ruby/object:Gem::Requirement
|
141
|
+
requirements:
|
142
|
+
- - ">="
|
143
|
+
- !ruby/object:Gem::Version
|
144
|
+
version: 0.48.0
|
131
145
|
description: ''
|
132
146
|
email:
|
133
147
|
- ben@gimbo.net
|
@@ -168,7 +182,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
168
182
|
version: '0'
|
169
183
|
requirements: []
|
170
184
|
rubyforge_project:
|
171
|
-
rubygems_version: 2.
|
185
|
+
rubygems_version: 2.6.11
|
172
186
|
signing_key:
|
173
187
|
specification_version: 4
|
174
188
|
summary: Allow ActiveRecord to share a connection to multiple databases on the same
|