active_record_host_pool 1.1.0 → 1.2.0
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/connection_adapter_mixin.rb +5 -3
- data/lib/active_record_host_pool/pool_proxy.rb +2 -1
- 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
- metadata +10 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f5dcc0c95ead619555c18514507bf2711f7790c7e120570a5daaadf6506f1250
|
4
|
+
data.tar.gz: 37d82a6b2c495872cfa5522bd588c7dd047afa5b9cdc376acd9a9c96aba21d44
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: dd36a23cbb9636ba2dda0f303776715e05aef42ddecafa583388b32c7c11adcae6a0285743eede486712559d20309fa5fe834bd44a9bc539c2cc985c3f80c344
|
7
|
+
data.tar.gz: d18bec930c1c6358d310461bd958fa3d92baee83e7de0d629783610809aea7f552ef98a1cc7482707cd8eaef4d592321a00f2210302132c31fead5d27b471962
|
@@ -32,7 +32,8 @@ module ActiveRecordHostPool
|
|
32
32
|
super
|
33
33
|
end
|
34
34
|
|
35
|
-
def
|
35
|
+
def self.ruby2_keywords(*); end unless respond_to?(:ruby2_keywords, true)
|
36
|
+
ruby2_keywords def execute_with_switching(*args)
|
36
37
|
if _host_pool_current_database && !_no_switch
|
37
38
|
_switch_connection
|
38
39
|
end
|
@@ -97,7 +98,7 @@ module ActiveRecord
|
|
97
98
|
module ConnectionAdapters
|
98
99
|
class ConnectionHandler
|
99
100
|
case "#{ActiveRecord::VERSION::MAJOR}.#{ActiveRecord::VERSION::MINOR}"
|
100
|
-
when '6.1'
|
101
|
+
when '6.1', '7.0'
|
101
102
|
|
102
103
|
:noop
|
103
104
|
|
@@ -122,6 +123,7 @@ ActiveRecord::ConnectionAdapters::Mysql2Adapter.include(ActiveRecordHostPool::Da
|
|
122
123
|
|
123
124
|
# In Rails 6.1 Connection Pools are no longer instantiated in #establish_connection but in a
|
124
125
|
# new pool method.
|
125
|
-
|
126
|
+
case "#{ActiveRecord::VERSION::MAJOR}.#{ActiveRecord::VERSION::MINOR}"
|
127
|
+
when '6.1', '7.0'
|
126
128
|
ActiveRecord::ConnectionAdapters::PoolConfig.prepend(ActiveRecordHostPool::PoolConfigPatch)
|
127
129
|
end
|
@@ -1,6 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
3
|
+
case "#{ActiveRecord::VERSION::MAJOR}.#{ActiveRecord::VERSION::MINOR}"
|
4
|
+
when '6.1', '7.0'
|
4
5
|
require 'active_record_host_pool/pool_proxy_6_1'
|
5
6
|
else
|
6
7
|
require 'active_record_host_pool/pool_proxy_legacy'
|
@@ -0,0 +1,150 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'delegate'
|
4
|
+
require 'active_record'
|
5
|
+
require 'active_record_host_pool/connection_adapter_mixin'
|
6
|
+
|
7
|
+
# this module sits in between ConnectionHandler and a bunch of different ConnectionPools (one per host).
|
8
|
+
# when a connection is requested, it goes like:
|
9
|
+
# ActiveRecordClass -> ConnectionHandler#connection
|
10
|
+
# ConnectionHandler#connection -> (find or create PoolProxy)
|
11
|
+
# PoolProxy -> shared list of Pools
|
12
|
+
# Pool actually gives back a connection, then PoolProxy turns this
|
13
|
+
# into a ConnectionProxy that can inform (on execute) which db we should be on.
|
14
|
+
|
15
|
+
module ActiveRecordHostPool
|
16
|
+
# Sits between ConnectionHandler and a bunch of different ConnectionPools (one per host).
|
17
|
+
class PoolProxy < Delegator
|
18
|
+
def initialize(pool_config)
|
19
|
+
super(pool_config)
|
20
|
+
@pool_config = pool_config
|
21
|
+
@config = pool_config.db_config.configuration_hash
|
22
|
+
end
|
23
|
+
|
24
|
+
def __getobj__
|
25
|
+
_connection_pool
|
26
|
+
end
|
27
|
+
|
28
|
+
def __setobj__(pool_config)
|
29
|
+
@pool_config = pool_config
|
30
|
+
@config = pool_config.db_config.configuration_hash
|
31
|
+
@_pool_key = nil
|
32
|
+
end
|
33
|
+
|
34
|
+
attr_reader :pool_config
|
35
|
+
|
36
|
+
def connection(*args)
|
37
|
+
real_connection = _connection_pool.connection(*args)
|
38
|
+
_connection_proxy_for(real_connection, @config[:database])
|
39
|
+
rescue Mysql2::Error, ActiveRecord::NoDatabaseError
|
40
|
+
_connection_pools.delete(_pool_key)
|
41
|
+
Kernel.raise
|
42
|
+
end
|
43
|
+
|
44
|
+
# by the time we are patched into ActiveRecord, the current thread has already established
|
45
|
+
# a connection. thus we need to patch both connection and checkout/checkin
|
46
|
+
def checkout(*args, &block)
|
47
|
+
cx = _connection_pool.checkout(*args, &block)
|
48
|
+
_connection_proxy_for(cx, @config[:database])
|
49
|
+
end
|
50
|
+
|
51
|
+
def checkin(cx)
|
52
|
+
cx = cx.unproxied
|
53
|
+
_connection_pool.checkin(cx)
|
54
|
+
end
|
55
|
+
|
56
|
+
def with_connection
|
57
|
+
cx = checkout
|
58
|
+
yield cx
|
59
|
+
ensure
|
60
|
+
checkin cx
|
61
|
+
end
|
62
|
+
|
63
|
+
def disconnect!
|
64
|
+
p = _connection_pool(false)
|
65
|
+
return unless p
|
66
|
+
|
67
|
+
p.disconnect!
|
68
|
+
p.automatic_reconnect = true if p.respond_to?(:automatic_reconnect=)
|
69
|
+
_clear_connection_proxy_cache
|
70
|
+
end
|
71
|
+
|
72
|
+
def automatic_reconnect=(value)
|
73
|
+
p = _connection_pool(false)
|
74
|
+
return unless p
|
75
|
+
|
76
|
+
p.automatic_reconnect = value if p.respond_to?(:automatic_reconnect=)
|
77
|
+
end
|
78
|
+
|
79
|
+
def clear_reloadable_connections!
|
80
|
+
_connection_pool.clear_reloadable_connections!
|
81
|
+
_clear_connection_proxy_cache
|
82
|
+
end
|
83
|
+
|
84
|
+
def release_connection(*args)
|
85
|
+
p = _connection_pool(false)
|
86
|
+
return unless p
|
87
|
+
|
88
|
+
p.release_connection(*args)
|
89
|
+
end
|
90
|
+
|
91
|
+
def flush!
|
92
|
+
p = _connection_pool(false)
|
93
|
+
return unless p
|
94
|
+
|
95
|
+
p.flush!
|
96
|
+
end
|
97
|
+
|
98
|
+
def discard!
|
99
|
+
p = _connection_pool(false)
|
100
|
+
return unless p
|
101
|
+
|
102
|
+
p.discard!
|
103
|
+
|
104
|
+
# All connections in the pool (even if they're currently
|
105
|
+
# leased!) have just been discarded, along with the pool itself.
|
106
|
+
# Any further interaction with the pool (except #pool_config and #schema_cache)
|
107
|
+
# is undefined.
|
108
|
+
# Remove the connection for the given key so a new one can be created in its place
|
109
|
+
_connection_pools.delete(_pool_key)
|
110
|
+
end
|
111
|
+
|
112
|
+
private
|
113
|
+
|
114
|
+
def _connection_pools
|
115
|
+
@@_connection_pools ||= {}
|
116
|
+
end
|
117
|
+
|
118
|
+
def _pool_key
|
119
|
+
@_pool_key ||= "#{@config[:host]}/#{@config[:port]}/#{@config[:socket]}/" \
|
120
|
+
"#{@config[:username]}/#{replica_configuration? && 'replica'}"
|
121
|
+
end
|
122
|
+
|
123
|
+
def _connection_pool(auto_create = true)
|
124
|
+
pool = _connection_pools[_pool_key]
|
125
|
+
if pool.nil? && auto_create
|
126
|
+
pool = _connection_pools[_pool_key] = ActiveRecord::ConnectionAdapters::ConnectionPool.new(@pool_config)
|
127
|
+
end
|
128
|
+
pool
|
129
|
+
end
|
130
|
+
|
131
|
+
def _connection_proxy_for(connection, database)
|
132
|
+
@connection_proxy_cache ||= {}
|
133
|
+
key = [connection, database]
|
134
|
+
|
135
|
+
@connection_proxy_cache[key] ||= begin
|
136
|
+
cx = ActiveRecordHostPool::ConnectionProxy.new(connection, database)
|
137
|
+
cx.execute('select 1')
|
138
|
+
cx
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
def _clear_connection_proxy_cache
|
143
|
+
@connection_proxy_cache = {}
|
144
|
+
end
|
145
|
+
|
146
|
+
def replica_configuration?
|
147
|
+
@config[:replica] || @config[:slave]
|
148
|
+
end
|
149
|
+
end
|
150
|
+
end
|
@@ -0,0 +1,152 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# For versions of Rails < 6.1
|
4
|
+
|
5
|
+
require 'delegate'
|
6
|
+
require 'active_record'
|
7
|
+
require 'active_record_host_pool/connection_adapter_mixin'
|
8
|
+
|
9
|
+
# this module sits in between ConnectionHandler and a bunch of different ConnectionPools (one per host).
|
10
|
+
# when a connection is requested, it goes like:
|
11
|
+
# ActiveRecordClass -> ConnectionHandler#connection
|
12
|
+
# ConnectionHandler#connection -> (find or create PoolProxy)
|
13
|
+
# PoolProxy -> shared list of Pools
|
14
|
+
# Pool actually gives back a connection, then PoolProxy turns this
|
15
|
+
# into a ConnectionProxy that can inform (on execute) which db we should be on.
|
16
|
+
|
17
|
+
module ActiveRecordHostPool
|
18
|
+
# Sits between ConnectionHandler and a bunch of different ConnectionPools (one per host).
|
19
|
+
class PoolProxy < Delegator
|
20
|
+
def initialize(spec)
|
21
|
+
super(spec)
|
22
|
+
@spec = spec
|
23
|
+
@config = spec.config
|
24
|
+
end
|
25
|
+
|
26
|
+
def __getobj__
|
27
|
+
_connection_pool
|
28
|
+
end
|
29
|
+
|
30
|
+
def __setobj__(spec)
|
31
|
+
@spec = spec
|
32
|
+
@config = spec.config
|
33
|
+
@_pool_key = nil
|
34
|
+
end
|
35
|
+
|
36
|
+
attr_reader :spec
|
37
|
+
|
38
|
+
def connection(*args)
|
39
|
+
real_connection = _connection_pool.connection(*args)
|
40
|
+
_connection_proxy_for(real_connection, @config[:database])
|
41
|
+
rescue Mysql2::Error, ActiveRecord::NoDatabaseError
|
42
|
+
_connection_pools.delete(_pool_key)
|
43
|
+
Kernel.raise
|
44
|
+
end
|
45
|
+
|
46
|
+
# by the time we are patched into ActiveRecord, the current thread has already established
|
47
|
+
# a connection. thus we need to patch both connection and checkout/checkin
|
48
|
+
def checkout(*args, &block)
|
49
|
+
cx = _connection_pool.checkout(*args, &block)
|
50
|
+
_connection_proxy_for(cx, @config[:database])
|
51
|
+
end
|
52
|
+
|
53
|
+
def checkin(cx)
|
54
|
+
cx = cx.unproxied
|
55
|
+
_connection_pool.checkin(cx)
|
56
|
+
end
|
57
|
+
|
58
|
+
def with_connection
|
59
|
+
cx = checkout
|
60
|
+
yield cx
|
61
|
+
ensure
|
62
|
+
checkin cx
|
63
|
+
end
|
64
|
+
|
65
|
+
def disconnect!
|
66
|
+
p = _connection_pool(false)
|
67
|
+
return unless p
|
68
|
+
|
69
|
+
p.disconnect!
|
70
|
+
p.automatic_reconnect = true if p.respond_to?(:automatic_reconnect=)
|
71
|
+
_clear_connection_proxy_cache
|
72
|
+
end
|
73
|
+
|
74
|
+
def automatic_reconnect=(value)
|
75
|
+
p = _connection_pool(false)
|
76
|
+
return unless p
|
77
|
+
|
78
|
+
p.automatic_reconnect = value if p.respond_to?(:automatic_reconnect=)
|
79
|
+
end
|
80
|
+
|
81
|
+
def clear_reloadable_connections!
|
82
|
+
_connection_pool.clear_reloadable_connections!
|
83
|
+
_clear_connection_proxy_cache
|
84
|
+
end
|
85
|
+
|
86
|
+
def release_connection(*args)
|
87
|
+
p = _connection_pool(false)
|
88
|
+
return unless p
|
89
|
+
|
90
|
+
p.release_connection(*args)
|
91
|
+
end
|
92
|
+
|
93
|
+
def flush!
|
94
|
+
p = _connection_pool(false)
|
95
|
+
return unless p
|
96
|
+
|
97
|
+
p.flush!
|
98
|
+
end
|
99
|
+
|
100
|
+
def discard!
|
101
|
+
p = _connection_pool(false)
|
102
|
+
return unless p
|
103
|
+
|
104
|
+
p.discard!
|
105
|
+
|
106
|
+
# All connections in the pool (even if they're currently
|
107
|
+
# leased!) have just been discarded, along with the pool itself.
|
108
|
+
# Any further interaction with the pool (except #spec and #schema_cache)
|
109
|
+
# is undefined.
|
110
|
+
# Remove the connection for the given key so a new one can be created in its place
|
111
|
+
_connection_pools.delete(_pool_key)
|
112
|
+
end
|
113
|
+
|
114
|
+
private
|
115
|
+
|
116
|
+
def _connection_pools
|
117
|
+
@@_connection_pools ||= {}
|
118
|
+
end
|
119
|
+
|
120
|
+
def _pool_key
|
121
|
+
@_pool_key ||= "#{@config[:host]}/#{@config[:port]}/#{@config[:socket]}/" \
|
122
|
+
"#{@config[:username]}/#{replica_configuration? && 'replica'}"
|
123
|
+
end
|
124
|
+
|
125
|
+
def _connection_pool(auto_create = true)
|
126
|
+
pool = _connection_pools[_pool_key]
|
127
|
+
if pool.nil? && auto_create
|
128
|
+
pool = _connection_pools[_pool_key] = ActiveRecord::ConnectionAdapters::ConnectionPool.new(@spec)
|
129
|
+
end
|
130
|
+
pool
|
131
|
+
end
|
132
|
+
|
133
|
+
def _connection_proxy_for(connection, database)
|
134
|
+
@connection_proxy_cache ||= {}
|
135
|
+
key = [connection, database]
|
136
|
+
|
137
|
+
@connection_proxy_cache[key] ||= begin
|
138
|
+
cx = ActiveRecordHostPool::ConnectionProxy.new(connection, database)
|
139
|
+
cx.execute('select 1')
|
140
|
+
cx
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
def _clear_connection_proxy_cache
|
145
|
+
@connection_proxy_cache = {}
|
146
|
+
end
|
147
|
+
|
148
|
+
def replica_configuration?
|
149
|
+
@config[:replica] || @config[:slave]
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
metadata
CHANGED
@@ -1,17 +1,17 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: active_record_host_pool
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Benjamin Quorning
|
8
8
|
- Gabe Martin-Dempesy
|
9
9
|
- Pierre Schambacher
|
10
10
|
- Ben Osheroff
|
11
|
-
autorequire:
|
11
|
+
autorequire:
|
12
12
|
bindir: bin
|
13
13
|
cert_chain: []
|
14
|
-
date: 2022-
|
14
|
+
date: 2022-10-13 00:00:00.000000000 Z
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
17
17
|
name: activerecord
|
@@ -22,7 +22,7 @@ dependencies:
|
|
22
22
|
version: 5.1.0
|
23
23
|
- - "<"
|
24
24
|
- !ruby/object:Gem::Version
|
25
|
-
version: '7.
|
25
|
+
version: '7.1'
|
26
26
|
type: :runtime
|
27
27
|
prerelease: false
|
28
28
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -32,7 +32,7 @@ dependencies:
|
|
32
32
|
version: 5.1.0
|
33
33
|
- - "<"
|
34
34
|
- !ruby/object:Gem::Version
|
35
|
-
version: '7.
|
35
|
+
version: '7.1'
|
36
36
|
- !ruby/object:Gem::Dependency
|
37
37
|
name: mysql2
|
38
38
|
requirement: !ruby/object:Gem::Requirement
|
@@ -163,6 +163,8 @@ files:
|
|
163
163
|
- lib/active_record_host_pool/connection_adapter_mixin.rb
|
164
164
|
- lib/active_record_host_pool/connection_proxy.rb
|
165
165
|
- lib/active_record_host_pool/pool_proxy.rb
|
166
|
+
- lib/active_record_host_pool/pool_proxy_6_1.rb
|
167
|
+
- lib/active_record_host_pool/pool_proxy_legacy.rb
|
166
168
|
- lib/active_record_host_pool/version.rb
|
167
169
|
- test/database.yml
|
168
170
|
- test/helper.rb
|
@@ -172,7 +174,7 @@ homepage: https://github.com/zendesk/active_record_host_pool
|
|
172
174
|
licenses:
|
173
175
|
- MIT
|
174
176
|
metadata: {}
|
175
|
-
post_install_message:
|
177
|
+
post_install_message:
|
176
178
|
rdoc_options: []
|
177
179
|
require_paths:
|
178
180
|
- lib
|
@@ -187,8 +189,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
187
189
|
- !ruby/object:Gem::Version
|
188
190
|
version: '0'
|
189
191
|
requirements: []
|
190
|
-
rubygems_version: 3.1
|
191
|
-
signing_key:
|
192
|
+
rubygems_version: 3.0.3.1
|
193
|
+
signing_key:
|
192
194
|
specification_version: 4
|
193
195
|
summary: Allow ActiveRecord to share a connection to multiple databases on the same
|
194
196
|
host
|