activerecord-bogacs 0.5.1 → 0.7.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/.github/workflows/test.yml +82 -0
- data/Gemfile +2 -15
- data/LICENSE.txt +1 -1
- data/README.md +37 -17
- data/Rakefile +8 -6
- data/activerecord-bogacs.gemspec +6 -6
- data/lib/active_record/bogacs/connection_handler.rb +36 -0
- data/lib/active_record/bogacs/default_pool.rb +256 -91
- data/lib/active_record/bogacs/false_pool.rb +97 -54
- data/lib/active_record/bogacs/pool_support.rb +26 -8
- data/lib/active_record/bogacs/railtie.rb +17 -0
- data/lib/active_record/bogacs/shareable_pool.rb +41 -46
- data/lib/active_record/bogacs/thread_safe/synchronized.rb +18 -22
- data/lib/active_record/bogacs/thread_safe.rb +3 -67
- data/lib/active_record/bogacs/validator.rb +15 -20
- data/lib/active_record/bogacs/version.rb +1 -1
- data/lib/active_record/bogacs.rb +6 -2
- data/lib/active_record/connection_adapters/adapter_compat.rb +63 -17
- data/lib/active_record/connection_adapters/pool_class.rb +33 -2
- data/lib/activerecord-bogacs.rb +1 -0
- data/test/active_record/bogacs/false_pool_test.rb +66 -78
- data/test/active_record/bogacs/shareable_pool/connection_pool_test.rb +2 -1
- data/test/active_record/bogacs/shareable_pool/connection_sharing_test.rb +2 -2
- data/test/active_record/bogacs/shareable_pool_helper.rb +1 -1
- data/test/active_record/bogacs/validator_test.rb +22 -28
- data/test/active_record/connection_pool_test_methods.rb +24 -20
- data/test/test_helper.rb +41 -26
- metadata +33 -17
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8272c1dff28e707a092e34ec3e95a0bcf76f31c7b38074da474db9e5cf520edd
|
4
|
+
data.tar.gz: fe9a92843c1b94098e9de4e85d830f96357aa8b49a0e769001eb14d37a71d334
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a9ccd085265c8f744dd7d7ef95dd38918ef2b37c029d1ad19a09322d727fa7a080f895ab14bab005cd54887402090798750a3ad9c1f6f7d0b8456a205ae7cd08
|
7
|
+
data.tar.gz: 40031eed7a1628094fc21d105006e32e06ab48b0890fa0abeb8379c2d513527a01c520e124438bb7dd380448e66cb8b3a2947beaf1cd15f1f2d074645b0b97d8
|
@@ -0,0 +1,82 @@
|
|
1
|
+
name: Test
|
2
|
+
|
3
|
+
on: [push, pull_request]
|
4
|
+
|
5
|
+
env:
|
6
|
+
JAVA_OPTS: '-XX:+TieredCompilation -XX:TieredStopAtLevel=1'
|
7
|
+
|
8
|
+
jobs:
|
9
|
+
|
10
|
+
rake-test:
|
11
|
+
runs-on: ubuntu-latest
|
12
|
+
services:
|
13
|
+
mysql:
|
14
|
+
image: mysql:5.7
|
15
|
+
env:
|
16
|
+
MYSQL_ALLOW_EMPTY_PASSWORD: yes
|
17
|
+
MYSQL_ROOT_PASSWORD: root
|
18
|
+
MYSQL_DATABASE: ar_bogacs
|
19
|
+
ports:
|
20
|
+
- 3306:3306
|
21
|
+
options: --health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=5s --health-retries=3
|
22
|
+
|
23
|
+
env:
|
24
|
+
AR_ADAPTER: mysql2
|
25
|
+
AR_USERNAME: root
|
26
|
+
AR_PASSWORD: root
|
27
|
+
AR_HOST: 127.0.0.1
|
28
|
+
AR_VERSION: "~> 4.2"
|
29
|
+
HIKARI_VERSION: 2.3.12
|
30
|
+
|
31
|
+
strategy:
|
32
|
+
matrix:
|
33
|
+
java-version: [ 11 ]
|
34
|
+
ruby-version: [ jruby-9.3.6.0 ]
|
35
|
+
include:
|
36
|
+
- java-version: 11
|
37
|
+
ruby-version: jruby-9.2.20.1
|
38
|
+
- java-version: 11
|
39
|
+
ruby-version: jruby-9.2.10.0
|
40
|
+
- java-version: 17
|
41
|
+
ruby-version: jruby-9.2.20.1
|
42
|
+
- java-version: 8
|
43
|
+
ruby-version: jruby-9.2.9.0
|
44
|
+
- java-version: 8
|
45
|
+
ruby-version: jruby-9.1.17.0
|
46
|
+
env:
|
47
|
+
AR_VERSION: "~> 4.1.14"
|
48
|
+
|
49
|
+
fail-fast: false
|
50
|
+
|
51
|
+
steps:
|
52
|
+
- name: check mysql from host
|
53
|
+
run: |
|
54
|
+
sudo apt install -y mysql-client
|
55
|
+
mysql --host 127.0.0.1 --port 3306 -uroot -proot -e "SHOW DATABASES"
|
56
|
+
|
57
|
+
- name: checkout
|
58
|
+
uses: actions/checkout@v2
|
59
|
+
|
60
|
+
- name: set up java ${{ matrix.java-version }}
|
61
|
+
uses: actions/setup-java@v1.4.3
|
62
|
+
with:
|
63
|
+
java-version: ${{ matrix.java-version }}
|
64
|
+
|
65
|
+
- name: set up ${{ matrix.ruby-version }}
|
66
|
+
uses: ruby/setup-ruby@v1
|
67
|
+
with:
|
68
|
+
ruby-version: ${{ matrix.ruby-version }}
|
69
|
+
|
70
|
+
- name: install bundler
|
71
|
+
run: jruby -S gem install bundler -v "~>2.2.28"
|
72
|
+
|
73
|
+
- name: bundle install
|
74
|
+
run: jruby -S bundle install
|
75
|
+
|
76
|
+
- name: download jars
|
77
|
+
run: jruby -rbundler/setup -S rake tomcat:jndi:download tomcat:jdbc:download tomcat:dbcp:download hikari:download
|
78
|
+
shell: bash
|
79
|
+
|
80
|
+
- name: rake test
|
81
|
+
run: jruby -rbundler/setup -S rake test
|
82
|
+
shell: bash
|
data/Gemfile
CHANGED
@@ -16,14 +16,6 @@ else
|
|
16
16
|
gem 'activerecord', :require => nil
|
17
17
|
end
|
18
18
|
|
19
|
-
if RUBY_VERSION.index('1.8') == 0
|
20
|
-
gem 'i18n', '< 0.7.0' # Gem::InstallError: i18n requires Ruby version >= 1.9.3
|
21
|
-
gem 'atomic', '1.1.16' # concurrent-ruby gem only for Ruby version >= 1.9.3
|
22
|
-
gem 'thread_safe', '~> 0.3'
|
23
|
-
else
|
24
|
-
gem 'concurrent-ruby', '~> 1.0.0', :require => nil
|
25
|
-
end
|
26
|
-
|
27
19
|
platform :jruby do
|
28
20
|
if version = ENV['AR_JDBC_VERSION']
|
29
21
|
if version.index('/') && ::File.exist?(version)
|
@@ -40,16 +32,11 @@ platform :jruby do
|
|
40
32
|
end
|
41
33
|
end
|
42
34
|
|
43
|
-
#gem 'thread_safe', :require => nil # "optional" - we can roll without it
|
44
|
-
|
45
|
-
if defined?(JRUBY_VERSION) && JRUBY_VERSION < '1.7.0'
|
46
|
-
gem 'jruby-openssl', :platform => :jruby
|
47
|
-
end
|
48
|
-
|
49
35
|
group :test do
|
50
36
|
gem 'jdbc-mysql', :require => nil, :platform => :jruby
|
51
37
|
gem 'jdbc-postgres', :require => nil, :platform => :jruby
|
38
|
+
gem 'jdbc-sqlite3', :require => nil, :platform => :jruby
|
52
39
|
|
53
40
|
gem 'mysql2', :require => nil, :platform => :mri
|
54
41
|
gem 'pg', :require => nil, :platform => :mri
|
55
|
-
end
|
42
|
+
end
|
data/LICENSE.txt
CHANGED
data/README.md
CHANGED
@@ -6,7 +6,7 @@ ActiveRecord (all-year) pooling "alternatives" ... in a relaxed 'spa' fashion.
|
|
6
6
|
|
7
7
|
Bogács is a village in Borsod-Abaúj-Zemplén county, Hungary.
|
8
8
|
|
9
|
-
**
|
9
|
+
**NOTE: do not put this on production if you do not understand the consequences!**
|
10
10
|
|
11
11
|
## Install
|
12
12
|
|
@@ -22,8 +22,8 @@ add this line to your application's *Gemfile*:
|
|
22
22
|
|
23
23
|
Bogacs' pools rely on a small monkey-patch that allows to change the AR pool.
|
24
24
|
The desired pool class needs to be set before `establish_connection` happens,
|
25
|
-
thus an initializer won't work, you might consider setting the
|
26
|
-
the bottom of your *application.rb* e.g. :
|
25
|
+
thus an initializer (under Rails) won't work, you might consider setting the
|
26
|
+
pool class at the bottom of your *application.rb* e.g. :
|
27
27
|
|
28
28
|
```ruby
|
29
29
|
Bundler.require(*Rails.groups)
|
@@ -34,19 +34,39 @@ module MyApp
|
|
34
34
|
end
|
35
35
|
end
|
36
36
|
|
37
|
-
# sample AR-Bogacs setup using the "
|
37
|
+
# sample AR-Bogacs setup using the "default" pool :
|
38
38
|
if Rails.env.production?
|
39
|
-
pool_class = ActiveRecord::Bogacs::
|
39
|
+
pool_class = ActiveRecord::Bogacs::DefaultPool
|
40
40
|
ActiveRecord::ConnectionAdapters::ConnectionHandler.connection_pool_class = pool_class
|
41
41
|
end
|
42
42
|
```
|
43
43
|
|
44
|
-
|
44
|
+
Alternatively, for `FalsePool`, there's a configuration convention (no need to path
|
45
|
+
and set the connection_pool_class) :
|
46
|
+
```yaml
|
47
|
+
production:
|
48
|
+
adapter: mysql2
|
49
|
+
<% if $servlet_context %>
|
50
|
+
jndi: java:comp/env/jdbc/mydb
|
51
|
+
pool: false # use AR::Bogacs::FalsePool
|
52
|
+
<% else %>
|
53
|
+
port: <%= ENV['DATABASE_PORT'] || 3306 %>
|
54
|
+
database: mydb
|
55
|
+
# ...
|
56
|
+
<% end %>
|
57
|
+
```
|
58
|
+
|
59
|
+
This works only as long as one doesn't set a custom connection handler, since
|
60
|
+
*Bogacs* only sets up its custom `ActiveRecord::Base.default_connection_handler`.
|
61
|
+
|
62
|
+
Pools are expected to work with older ActiveRecord versions: 3.x as well as 4.x.
|
45
63
|
|
46
64
|
### [Default Pool][2]
|
47
65
|
|
48
|
-
Meant as a back-port for users stuck with old Rails versions (< 4.0)
|
49
|
-
facing potential (pool related) concurrency bugs e.g. with
|
66
|
+
Meant, primarily, as a back-port for users stuck with old Rails versions (< 4.0)
|
67
|
+
on production, facing potential (pool related) concurrency bugs e.g. with highly
|
68
|
+
concurrent loads under JRuby, although it also enhances some of the thread locking
|
69
|
+
issues present in 4.x's pool.
|
50
70
|
|
51
71
|
Based on pool code from 4.x (which works much better than any previous version),
|
52
72
|
with a few minor tunings and extensions such as `pool_initial: 0.5` which allows
|
@@ -56,7 +76,7 @@ to specify how many connections to initialize in advance when the pool is create
|
|
56
76
|
|
57
77
|
The false pool won't do any actual pooling, it is assumed that an underlying pool
|
58
78
|
is configured. Still, it does maintain a hash of AR connections mapped to threads.
|
59
|
-
Ignores pool related
|
79
|
+
Ignores pool related configuration such as `pool: 42` or `checkout_timeout: 2.5`.
|
60
80
|
|
61
81
|
**NOTE:** be sure to configure an underlying pool e.g. with Trinidad (using the
|
62
82
|
default Tomcat JDBC pool) :
|
@@ -70,7 +90,7 @@ default Tomcat JDBC pool) :
|
|
70
90
|
mysql_dbpool:
|
71
91
|
url: jdbc:mysql:///my_production
|
72
92
|
username: root
|
73
|
-
jndi: jdbc/
|
93
|
+
jndi: jdbc/MyDB
|
74
94
|
initialSize: <%= ENV['POOL_INITIAL'] || 25 %> # connections created on start
|
75
95
|
maxActive: <%= ENV['POOL_SIZE'] || 100 %> # default 100 (AR pool: size)
|
76
96
|
maxIdle: <%= ENV['POOL_SIZE'] || 100 %> # max connections kept in the pool
|
@@ -88,7 +108,7 @@ following configuration :
|
|
88
108
|
```
|
89
109
|
production:
|
90
110
|
adapter: mysql2
|
91
|
-
jndi: java:/comp/env/jdbc/
|
111
|
+
jndi: java:/comp/env/jdbc/MyDB
|
92
112
|
```
|
93
113
|
|
94
114
|
**NOTE:** when using `FalsePool` there's nothing to configure (in *database.yml*)!
|
@@ -97,7 +117,7 @@ production:
|
|
97
117
|
|
98
118
|
This pool allows for a database connection to be "shared" among threads, this is
|
99
119
|
very **dangerous** normally. You will need to understand the underlying driver's
|
100
|
-
connection whether
|
120
|
+
connection implementation (whether its thread-safe).
|
101
121
|
|
102
122
|
You'll need to manually declare blocks that run with a shared connection (**make
|
103
123
|
sure** only read operations happen within such blocks) similar to the built-in
|
@@ -109,15 +129,15 @@ cache_fetch( [ 'user', user_id ] ) do
|
|
109
129
|
end
|
110
130
|
```
|
111
131
|
|
112
|
-
The pool
|
113
|
-
|
114
|
-
just like
|
132
|
+
The pool "might" share connections among such blocks but only if it runs out of
|
133
|
+
all connections (pool size is reached), until than it will always prefer checking
|
134
|
+
out a connection just like `with_connection` does.
|
115
135
|
|
116
|
-
|
136
|
+
Tested with ActiveRecord-JDBC-Adapter using the official Postgres' driver (< 42).
|
117
137
|
|
118
138
|
## Copyright
|
119
139
|
|
120
|
-
Copyright (c)
|
140
|
+
Copyright (c) 2018 [Karol Bucek](http://kares.org).
|
121
141
|
See LICENSE (http://en.wikipedia.org/wiki/MIT_License) for details.
|
122
142
|
|
123
143
|
[0]: http://res.cloudinary.com/kares/image/upload/c_scale,h_600,w_800/v1406451696/bogacs.jpg
|
data/Rakefile
CHANGED
@@ -105,9 +105,11 @@ def _download(uri, download_dir, as_file_name)
|
|
105
105
|
FileUtils.rm_r temp_dir
|
106
106
|
end
|
107
107
|
|
108
|
+
MAVEN_BASE_URL = 'https://repo.maven.apache.org/maven2'
|
109
|
+
|
108
110
|
namespace :tomcat do
|
109
111
|
|
110
|
-
tomcat_maven_repo =
|
112
|
+
tomcat_maven_repo = "#{MAVEN_BASE_URL}/org/apache/tomcat"
|
111
113
|
download_dir = File.expand_path('test/jars', File.dirname(__FILE__))
|
112
114
|
version_default = '7.0.64'
|
113
115
|
|
@@ -191,7 +193,7 @@ end
|
|
191
193
|
|
192
194
|
namespace :dbcp do # a.k.a DBCP2
|
193
195
|
|
194
|
-
commons_repo =
|
196
|
+
commons_repo = "#{MAVEN_BASE_URL}/org/apache/commons"
|
195
197
|
download_dir = File.expand_path('test/jars', File.dirname(__FILE__))
|
196
198
|
version_default = '2.0.1'
|
197
199
|
|
@@ -213,7 +215,7 @@ end
|
|
213
215
|
|
214
216
|
namespace :c3p0 do
|
215
217
|
|
216
|
-
mchange_base_repo =
|
218
|
+
mchange_base_repo = "#{MAVEN_BASE_URL}/com/mchange"
|
217
219
|
download_dir = File.expand_path('test/jars', File.dirname(__FILE__))
|
218
220
|
c3p0_version = '0.9.5'
|
219
221
|
mchange_commons_version = '0.2.9'
|
@@ -242,9 +244,9 @@ end
|
|
242
244
|
|
243
245
|
namespace :hikari do
|
244
246
|
|
245
|
-
hikari_base_repo =
|
246
|
-
slf4j_base_repo =
|
247
|
-
javassist_base_repo =
|
247
|
+
hikari_base_repo = "#{MAVEN_BASE_URL}/com/zaxxer"
|
248
|
+
slf4j_base_repo = "#{MAVEN_BASE_URL}/org/slf4j"
|
249
|
+
javassist_base_repo = "#{MAVEN_BASE_URL}/org/javassist"
|
248
250
|
download_dir = File.expand_path('test/jars', File.dirname(__FILE__))
|
249
251
|
hikari_version = '1.4.0'
|
250
252
|
slf4j_version = '1.7.10'
|
data/activerecord-bogacs.gemspec
CHANGED
@@ -9,10 +9,9 @@ Gem::Specification.new do |gem|
|
|
9
9
|
gem.authors = ['Karol Bucek']
|
10
10
|
gem.email = ['self@kares.org']
|
11
11
|
gem.description = %q{Improved ActiveRecord::ConnectionAdapters::ConnectionPool alternatives}
|
12
|
-
gem.summary = 'Bogacs contains several pool implementations that can be used as a replacement '
|
13
|
-
"for ActiveRecord's built-in pool, e.g. DefaultPool is an upstream tuned version with an API "
|
14
|
-
'that is compatible with older AR versions.'
|
15
|
-
"\n\nNOTE: you'll need concurrent-ruby or thread_safe gem."
|
12
|
+
gem.summary = 'Bogacs contains several pool implementations that can be used as a replacement ' +
|
13
|
+
"for ActiveRecord's built-in pool, e.g. DefaultPool is an upstream tuned version with an API " +
|
14
|
+
'that is compatible with older AR versions.'
|
16
15
|
gem.homepage = "http://github.com/kares/activerecord-bogacs"
|
17
16
|
gem.licenses = ['MIT']
|
18
17
|
|
@@ -21,8 +20,9 @@ Gem::Specification.new do |gem|
|
|
21
20
|
gem.test_files = gem.files.grep(%r{^test/})
|
22
21
|
gem.require_paths = ["lib"]
|
23
22
|
|
24
|
-
gem.
|
23
|
+
gem.add_dependency 'activerecord', '< 6' # '>= 4.0' # depends on: concurrent-ruby ~> 1.0, >= 1.0.2
|
24
|
+
gem.add_dependency 'concurrent-ruby', '~> 1.0'
|
25
25
|
|
26
|
-
gem.add_development_dependency 'rake'
|
26
|
+
gem.add_development_dependency 'rake'
|
27
27
|
gem.add_development_dependency 'test-unit', '~> 2.5'
|
28
28
|
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'active_record/version'
|
2
|
+
|
3
|
+
require 'active_record/connection_adapters/abstract/connection_pool'
|
4
|
+
|
5
|
+
module ActiveRecord
|
6
|
+
module Bogacs
|
7
|
+
class ConnectionHandler < ConnectionAdapters::ConnectionHandler
|
8
|
+
|
9
|
+
if ActiveRecord::VERSION::MAJOR < 5
|
10
|
+
|
11
|
+
def establish_connection(owner, spec)
|
12
|
+
@class_to_pool.clear
|
13
|
+
if spec.config[:pool].eql? false
|
14
|
+
owner_to_pool[owner.name] = ActiveRecord::Bogacs::FalsePool.new(spec)
|
15
|
+
else # super
|
16
|
+
owner_to_pool[owner.name] = ActiveRecord::ConnectionAdapters::ConnectionPool.new(spec)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
else
|
21
|
+
|
22
|
+
def establish_connection(config) # (spec) in 5.0
|
23
|
+
pool = super
|
24
|
+
spec = pool.spec
|
25
|
+
if spec.config[:pool].eql? false
|
26
|
+
owner_to_pool[spec.name] = ActiveRecord::Bogacs::FalsePool.new(spec)
|
27
|
+
else
|
28
|
+
pool
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|