advanced_connection 0.5.12 → 0.5.13
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile.lock +4 -17
- data/Rakefile +0 -40
- data/advanced_connection.gemspec +25 -25
- data/lib/advanced_connection/active_record_ext/abstract_adapter.rb +4 -0
- data/lib/advanced_connection/active_record_ext/connection_pool/idle_manager.rb +64 -32
- data/lib/advanced_connection/active_record_ext/connection_pool/queues.rb +2 -2
- data/lib/advanced_connection/config.rb +1 -1
- data/lib/advanced_connection/version.rb +1 -1
- metadata +2 -16
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6d9bda6b436e364dda841af17bf2b2915d3e261d
|
4
|
+
data.tar.gz: 6248d54d405b47f4bb26d8c38d3a102b71d78342
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4ad06944f5895088cdf3c3b0edb8fea2f329a8f77b9a77ec5a0f76fe73fa6ca7d63f61c99d6227fa7a1302e817efc780b0cb97c126604976c3f1c7caf125db4c
|
7
|
+
data.tar.gz: 7d7ae267de0aa0973ea4ad381c01b8ce9ec07ee65f1be3dcb65672ed79e46e1ca2389e97559d12b7d99c15ea5edd1d27a07aaf700a4bf1f64a6ebfb802ed76b4
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
advanced_connection (0.5.
|
4
|
+
advanced_connection (0.5.13)
|
5
5
|
activerecord (~> 4.1)
|
6
6
|
activesupport (~> 4.1)
|
7
7
|
rails (~> 4.1)
|
@@ -46,11 +46,8 @@ GEM
|
|
46
46
|
tzinfo (~> 1.1)
|
47
47
|
arel (6.0.3)
|
48
48
|
builder (3.2.2)
|
49
|
-
charlock_holmes (0.7.3)
|
50
49
|
coderay (1.1.1)
|
51
50
|
concurrent-ruby (1.0.1)
|
52
|
-
copyright-header (1.0.15)
|
53
|
-
github-linguist (~> 2.6)
|
54
51
|
coveralls (0.8.13)
|
55
52
|
json (~> 1.8)
|
56
53
|
simplecov (~> 0.11.0)
|
@@ -60,15 +57,9 @@ GEM
|
|
60
57
|
diff-lcs (1.2.5)
|
61
58
|
docile (1.1.5)
|
62
59
|
erubis (2.7.0)
|
63
|
-
escape_utils (1.0.1)
|
64
60
|
ffi (1.9.10)
|
65
61
|
ffi (1.9.10-java)
|
66
62
|
formatador (0.2.5)
|
67
|
-
github-linguist (2.12.0)
|
68
|
-
charlock_holmes (~> 0.7.3)
|
69
|
-
escape_utils (~> 1.0.1)
|
70
|
-
mime-types (~> 1.19)
|
71
|
-
pygments.rb (~> 0.6.0)
|
72
63
|
globalid (0.3.6)
|
73
64
|
activesupport (>= 4.1.0)
|
74
65
|
guard (2.13.0)
|
@@ -97,7 +88,9 @@ GEM
|
|
97
88
|
mail (2.6.4)
|
98
89
|
mime-types (>= 1.16, < 4)
|
99
90
|
method_source (0.8.2)
|
100
|
-
mime-types (
|
91
|
+
mime-types (3.0)
|
92
|
+
mime-types-data (~> 3.2015)
|
93
|
+
mime-types-data (3.2016.0221)
|
101
94
|
mini_portile2 (2.0.0)
|
102
95
|
minitest (5.8.4)
|
103
96
|
nenv (0.3.0)
|
@@ -107,7 +100,6 @@ GEM
|
|
107
100
|
nenv (~> 0.1)
|
108
101
|
shellany (~> 0.0)
|
109
102
|
pg (0.18.4)
|
110
|
-
posix-spawn (0.3.11)
|
111
103
|
pry (0.10.3)
|
112
104
|
coderay (~> 1.1.0)
|
113
105
|
method_source (~> 0.8.1)
|
@@ -119,9 +111,6 @@ GEM
|
|
119
111
|
spoon (~> 0.0)
|
120
112
|
pry-nav (0.2.4)
|
121
113
|
pry (>= 0.9.10, < 0.11.0)
|
122
|
-
pygments.rb (0.6.3)
|
123
|
-
posix-spawn (~> 0.3.6)
|
124
|
-
yajl-ruby (~> 1.2.0)
|
125
114
|
rabbitt-githooks (1.6.1)
|
126
115
|
rainbow (~> 2.0.0)
|
127
116
|
thor (~> 0.19.1)
|
@@ -198,7 +187,6 @@ GEM
|
|
198
187
|
tins (1.6.0)
|
199
188
|
tzinfo (1.2.2)
|
200
189
|
thread_safe (~> 0.1)
|
201
|
-
yajl-ruby (1.2.1)
|
202
190
|
|
203
191
|
PLATFORMS
|
204
192
|
java
|
@@ -206,7 +194,6 @@ PLATFORMS
|
|
206
194
|
|
207
195
|
DEPENDENCIES
|
208
196
|
advanced_connection!
|
209
|
-
copyright-header (~> 1.0.15)
|
210
197
|
coveralls (~> 0.8.13)
|
211
198
|
guard-rspec (~> 4.6.4)
|
212
199
|
pg (~> 0.18.4)
|
data/Rakefile
CHANGED
@@ -91,46 +91,6 @@ namespace :db do
|
|
91
91
|
end
|
92
92
|
end
|
93
93
|
|
94
|
-
namespace :copyright do
|
95
|
-
namespace :headers do
|
96
|
-
desc 'add copyright headers'
|
97
|
-
task :add do
|
98
|
-
require 'copyright_header'
|
99
|
-
|
100
|
-
args = {
|
101
|
-
license: 'MIT',
|
102
|
-
copyright_software: 'Advanced Connection',
|
103
|
-
copyright_software_description: "A Rails plugin providing an Idle Database Connection Manager",
|
104
|
-
copyright_holders: ['Finalsite, LLC', 'Carl P. Corliss <carl.corliss@finalsite.com>'],
|
105
|
-
copyright_years: ['2016'],
|
106
|
-
add_path: 'lib',
|
107
|
-
output_dir: '.'
|
108
|
-
}
|
109
|
-
|
110
|
-
command_line = CopyrightHeader::CommandLine.new( args )
|
111
|
-
command_line.execute
|
112
|
-
end
|
113
|
-
|
114
|
-
desc 'remove copyright headers'
|
115
|
-
task :remove do
|
116
|
-
require 'copyright_header'
|
117
|
-
|
118
|
-
args = {
|
119
|
-
license: 'MIT',
|
120
|
-
copyright_software: 'Advanced Connection',
|
121
|
-
copyright_software_description: "A Rails plugin providing an Idle Database Connection Manager",
|
122
|
-
copyright_holders: ['Finalsite, LLC', 'Carl P. Corliss <carl.corliss@finalsite.com>'],
|
123
|
-
copyright_years: ['2016'],
|
124
|
-
remove_path: 'lib',
|
125
|
-
output_dir: '.'
|
126
|
-
}
|
127
|
-
|
128
|
-
command_line = CopyrightHeader::CommandLine.new( args )
|
129
|
-
command_line.execute
|
130
|
-
end
|
131
|
-
end
|
132
|
-
end
|
133
|
-
|
134
94
|
namespace :postgres do
|
135
95
|
require 'active_record'
|
136
96
|
|
data/advanced_connection.gemspec
CHANGED
@@ -1,22 +1,22 @@
|
|
1
|
-
$:.push File.expand_path(
|
1
|
+
$:.push File.expand_path('../lib', __FILE__)
|
2
2
|
|
3
3
|
# Maintain your gem's version:
|
4
|
-
require
|
4
|
+
require 'advanced_connection/version'
|
5
5
|
|
6
6
|
# Describe your gem and declare its dependencies:
|
7
7
|
Gem::Specification.new do |spec|
|
8
|
-
spec.name =
|
8
|
+
spec.name = 'advanced_connection'
|
9
9
|
spec.version = AdvancedConnection::VERSION
|
10
|
-
spec.authors = [
|
11
|
-
spec.email = [
|
12
|
-
spec.homepage =
|
13
|
-
spec.summary =
|
14
|
-
spec.description =
|
15
|
-
spec.license =
|
10
|
+
spec.authors = ['Carl P. Corliss']
|
11
|
+
spec.email = ['carl.corliss@finalsite.com']
|
12
|
+
spec.homepage = 'https://github.com/finalsite/advanced_connection'
|
13
|
+
spec.summary = 'Provides advanced connection options for rails connection pools'
|
14
|
+
spec.description = 'Adds idle connection management, statement pooling, and other advanced connection features'
|
15
|
+
spec.license = 'MIT'
|
16
16
|
|
17
17
|
spec.files = `git ls-files`.split($/)
|
18
18
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
-
spec.require_paths = [
|
19
|
+
spec.require_paths = ['lib']
|
20
20
|
|
21
21
|
# eventually support this:
|
22
22
|
# spec.required_engine_version = {
|
@@ -24,27 +24,27 @@ Gem::Specification.new do |spec|
|
|
24
24
|
# :jruby => '~> 1.7',
|
25
25
|
# }
|
26
26
|
|
27
|
-
spec.add_runtime_dependency
|
28
|
-
spec.add_runtime_dependency
|
29
|
-
spec.add_runtime_dependency
|
27
|
+
spec.add_runtime_dependency 'rails', '~> 4.1'
|
28
|
+
spec.add_runtime_dependency 'activerecord', '~> 4.1'
|
29
|
+
spec.add_runtime_dependency 'activesupport', '~> 4.1'
|
30
30
|
|
31
|
-
spec.add_development_dependency
|
32
|
-
spec.add_development_dependency
|
33
|
-
spec.add_development_dependency
|
34
|
-
spec.add_development_dependency
|
35
|
-
spec.add_development_dependency
|
31
|
+
spec.add_development_dependency 'rake', '~> 10.5.0'
|
32
|
+
spec.add_development_dependency 'rack', '~> 1.6.4'
|
33
|
+
spec.add_development_dependency 'rspec', '~> 3.4.0'
|
34
|
+
spec.add_development_dependency 'rspec-its', '~> 1.2.0'
|
35
|
+
spec.add_development_dependency 'rspec-collection_matchers', '~> 1.1.2'
|
36
36
|
|
37
37
|
# optional dependencies
|
38
38
|
if RUBY_ENGINE == 'jruby'
|
39
|
-
spec.add_development_dependency
|
39
|
+
spec.add_development_dependency 'activerecord-jdbcpostgresql-adapter', '~> 1.3.19'
|
40
|
+
spec.add_development_dependency 'puma', '~> 3.4.0'
|
40
41
|
else
|
41
|
-
spec.add_development_dependency
|
42
|
-
spec.add_development_dependency
|
43
|
-
spec.add_development_dependency
|
42
|
+
spec.add_development_dependency 'pg', '~> 0.18.4'
|
43
|
+
spec.add_development_dependency 'pry', '~> 0.10.3'
|
44
|
+
spec.add_development_dependency 'pry-nav', '~> 0.2.4'
|
44
45
|
end
|
45
46
|
|
46
|
-
spec.add_development_dependency
|
47
|
-
spec.add_development_dependency
|
47
|
+
spec.add_development_dependency 'guard-rspec', '~> 4.6.4'
|
48
|
+
spec.add_development_dependency 'coveralls', '~> 0.8.13'
|
48
49
|
spec.add_development_dependency 'rabbitt-githooks', '~> 1.6.0'
|
49
|
-
spec.add_development_dependency 'copyright-header', '~> 1.0.15'
|
50
50
|
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
|
1
|
+
|
2
2
|
# Copyright (C) 2016 Finalsite, LLC
|
3
3
|
# Copyright (C) 2016 Carl P. Corliss <carl.corliss@finalsite.com>
|
4
4
|
#
|
@@ -32,13 +32,48 @@ module AdvancedConnection::ActiveRecordExt
|
|
32
32
|
|
33
33
|
class IdleManager
|
34
34
|
attr_accessor :interval
|
35
|
-
attr_reader :thread
|
35
|
+
attr_reader :thread, :logger
|
36
36
|
private :thread
|
37
37
|
|
38
38
|
def initialize(pool, interval)
|
39
39
|
@pool = pool
|
40
40
|
@interval = interval.to_i
|
41
41
|
@thread = nil
|
42
|
+
@logger = ActiveSupport::Logger.new(Rails.root.join('log', 'idle_manager.log'))
|
43
|
+
@logger.level = Rails.logger.level
|
44
|
+
end
|
45
|
+
|
46
|
+
def log_info(format, *args)
|
47
|
+
@logger.info(format("#{idle_stats} #{format}", *args))
|
48
|
+
end
|
49
|
+
|
50
|
+
def log_debug(format, *args)
|
51
|
+
@logger.debug(format("#{idle_stats} #{format}", *args))
|
52
|
+
end
|
53
|
+
|
54
|
+
def log_warn(format, *args)
|
55
|
+
@logger.debug(format("#{idle_stats} #{format}", *args))
|
56
|
+
end
|
57
|
+
|
58
|
+
def dump_stats
|
59
|
+
if (stats_dump = Rails.root.join('tmp', 'dump-idle-stats.txt')).exist?
|
60
|
+
log_info "Dumping statistics"
|
61
|
+
id_size = self.object_id.to_s.size
|
62
|
+
@logger.info(format("%3s: %#{id_size}s\t%9s\t%9s", 'IDX', 'OID', 'AGE', 'IDLE'))
|
63
|
+
@pool.idle_connections.each_with_index do |connection, index|
|
64
|
+
@logger.info(format("%3d: %#{id_size}d\t%9d\t%9d",
|
65
|
+
index, connection.object_id, connection.instance_age, connection.idle_time))
|
66
|
+
end
|
67
|
+
!!(stats_dump.unlink rescue true)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def idle_stats
|
72
|
+
stats = @pool.pool_statistics
|
73
|
+
format(
|
74
|
+
"[#{Time.now}] IdleManager (Actv:%d,Avail:%d,Idle:%d,Total:%d):",
|
75
|
+
stats.active, stats.available, stats.idle, stats.total,
|
76
|
+
)
|
42
77
|
end
|
43
78
|
|
44
79
|
def status
|
@@ -63,19 +98,23 @@ module AdvancedConnection::ActiveRecordExt
|
|
63
98
|
return unless @interval > 0
|
64
99
|
|
65
100
|
@thread ||= Thread.new(@pool, @interval) { |pool, interval|
|
66
|
-
|
101
|
+
log_info("starting idle manager; running every #{interval} seconds")
|
67
102
|
|
68
103
|
loop do
|
69
104
|
sleep interval
|
70
105
|
|
71
106
|
begin
|
72
107
|
start = Time.now
|
73
|
-
|
108
|
+
dump_stats
|
109
|
+
|
110
|
+
log_debug("beginning idle connection cleanup")
|
74
111
|
pool.remove_idle_connections
|
75
|
-
|
112
|
+
|
113
|
+
log_debug("beginning idle connection warmup")
|
76
114
|
pool.create_idle_connections
|
115
|
+
|
77
116
|
finish = (Time.now - start).round(6)
|
78
|
-
|
117
|
+
log_info("finished idle connection tasks in #{finish} seconds; next run in #{interval} seconds")
|
79
118
|
rescue => e
|
80
119
|
Rails.logger.error "#{e.class.name}: #{e.message}"
|
81
120
|
e.backtrace.each { |line| Rails.logger.error line }
|
@@ -94,6 +133,7 @@ module AdvancedConnection::ActiveRecordExt
|
|
94
133
|
when :prefer_older then Queues::OldAgeBiased.new
|
95
134
|
when :prefer_younger then Queues::YoungAgeBiased.new
|
96
135
|
when :lifo, :stack then Queues::Stack.new
|
136
|
+
when :fifo, :queue then Queues::FIFO.new
|
97
137
|
else
|
98
138
|
Rails.logger.warn "Unknown queue_type #{queue_type.inspect} - using standard FIFO instead"
|
99
139
|
Queues::FIFO.new
|
@@ -151,7 +191,7 @@ module AdvancedConnection::ActiveRecordExt
|
|
151
191
|
|
152
192
|
def checkin_with_last_checked_in(conn)
|
153
193
|
conn.last_checked_in = Time.now
|
154
|
-
|
194
|
+
idle_manager.debug "checking in connection #{conn.object_id} at #{conn.last_checked_in}"
|
155
195
|
checkin_without_last_checked_in(conn)
|
156
196
|
end
|
157
197
|
|
@@ -213,7 +253,7 @@ module AdvancedConnection::ActiveRecordExt
|
|
213
253
|
|
214
254
|
return unless slots >= count
|
215
255
|
|
216
|
-
|
256
|
+
idle_manager.log_info "Warming up #{count} connection#{count > 1 ? 's' : ''}"
|
217
257
|
synchronize do
|
218
258
|
count.times {
|
219
259
|
conn = checkout_new_connection
|
@@ -242,27 +282,36 @@ module AdvancedConnection::ActiveRecordExt
|
|
242
282
|
|
243
283
|
def remove_idle_connections
|
244
284
|
# don't attempt to remove idle connections if we have threads waiting
|
245
|
-
|
285
|
+
if @available.num_waiting > 0
|
286
|
+
idle_manager.log_warn "Cannot reap while threads actively waiting on db connections"
|
287
|
+
return
|
288
|
+
end
|
246
289
|
|
247
290
|
idle_conns = idle_connections
|
248
291
|
idle_count = idle_conns.size
|
249
292
|
|
250
|
-
|
293
|
+
unless idle_count > max_idle_connections
|
294
|
+
idle_manager.log_warn "idle count (#{idle_count}) does not exceed max idle connections (#{max_idle_connections}); skipping reap."
|
295
|
+
return
|
296
|
+
end
|
251
297
|
|
252
298
|
cull_count = (idle_count - max_idle_connections)
|
253
299
|
|
254
300
|
culled = 0
|
255
301
|
idle_conns.each_with_index do |conn, idx|
|
256
|
-
last_ci = (Time.now - conn.last_checked_in).to_f
|
257
302
|
if idx < cull_count
|
258
|
-
|
259
|
-
|
303
|
+
if remove_connection(conn)
|
304
|
+
culled += 1
|
305
|
+
idle_manager.log_info "culled connection ##{idx} id##{conn.object_id} - age:#{conn.instance_age.to_i} idle_time:#{conn.idle_time.to_i}"
|
306
|
+
else
|
307
|
+
idle_manager.log_info "kept connection ##{idx} id##{conn.object_id} - age:#{conn.instance_age.to_i} idle_time:#{conn.idle_time.to_i}"
|
308
|
+
end
|
260
309
|
else
|
261
|
-
|
310
|
+
idle_manager.log_info "kept connection ##{idx} id##{conn.object_id} - age:#{conn.instance_age.to_i} idle_time:#{conn.idle_time.to_i}"
|
262
311
|
end
|
263
312
|
end
|
264
313
|
|
265
|
-
|
314
|
+
idle_manager.log_info "culled %d connections" % culled
|
266
315
|
end
|
267
316
|
|
268
317
|
private
|
@@ -275,23 +324,6 @@ module AdvancedConnection::ActiveRecordExt
|
|
275
324
|
end
|
276
325
|
true
|
277
326
|
end
|
278
|
-
|
279
|
-
def idle_message(format, *args)
|
280
|
-
stats = pool_statistics
|
281
|
-
format(
|
282
|
-
"IdleManager (Actv:%d,Avail:%d,Idle:%d,Total:%d): #{format}",
|
283
|
-
stats.active, stats.available, stats.idle, stats.total,
|
284
|
-
*args
|
285
|
-
)
|
286
|
-
end
|
287
|
-
|
288
|
-
def idle_debug(format, *args)
|
289
|
-
Rails.logger.debug idle_message(format, *args)
|
290
|
-
end
|
291
|
-
|
292
|
-
def idle_info(format, *args)
|
293
|
-
Rails.logger.info idle_message(format, *args)
|
294
|
-
end
|
295
327
|
end
|
296
328
|
end
|
297
329
|
end
|
@@ -46,13 +46,13 @@ module AdvancedConnection::ActiveRecordExt
|
|
46
46
|
|
47
47
|
class YoungAgeBiased < AgeSorted
|
48
48
|
def remove
|
49
|
-
@queue.
|
49
|
+
@queue.shift
|
50
50
|
end
|
51
51
|
end
|
52
52
|
|
53
53
|
class OldAgeBiased < AgeSorted
|
54
54
|
def remove
|
55
|
-
@queue.
|
55
|
+
@queue.pop
|
56
56
|
end
|
57
57
|
end
|
58
58
|
end
|
@@ -45,7 +45,7 @@ module AdvancedConnection
|
|
45
45
|
min_idle_connections: 0,
|
46
46
|
max_idle_connections: ::Float::INFINITY,
|
47
47
|
max_idle_time: 0,
|
48
|
-
idle_check_interval:
|
48
|
+
idle_check_interval: nil,
|
49
49
|
callbacks: ActiveSupport::OrderedOptions.new
|
50
50
|
).freeze unless defined? DEFAULT_CONFIG
|
51
51
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: advanced_connection
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.5.
|
4
|
+
version: 0.5.13
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Carl P. Corliss
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-
|
11
|
+
date: 2016-05-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -206,20 +206,6 @@ dependencies:
|
|
206
206
|
- - "~>"
|
207
207
|
- !ruby/object:Gem::Version
|
208
208
|
version: 1.6.0
|
209
|
-
- !ruby/object:Gem::Dependency
|
210
|
-
name: copyright-header
|
211
|
-
requirement: !ruby/object:Gem::Requirement
|
212
|
-
requirements:
|
213
|
-
- - "~>"
|
214
|
-
- !ruby/object:Gem::Version
|
215
|
-
version: 1.0.15
|
216
|
-
type: :development
|
217
|
-
prerelease: false
|
218
|
-
version_requirements: !ruby/object:Gem::Requirement
|
219
|
-
requirements:
|
220
|
-
- - "~>"
|
221
|
-
- !ruby/object:Gem::Version
|
222
|
-
version: 1.0.15
|
223
209
|
description: Adds idle connection management, statement pooling, and other advanced
|
224
210
|
connection features
|
225
211
|
email:
|