activerecord_connection_reaper 0.2.0 → 0.4.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 32f5626f8dd3cf90b2b020485814417cacd487528ec1c0d994e8ab1e55628f8a
4
- data.tar.gz: 7020099fc782b21c78cd8522afee666a23954befc40d9f17a9b6254d31832b0b
3
+ metadata.gz: cde5ce57597f3080ebda91544487f81477143a38d99355e4eb8ee4e70d0b75e3
4
+ data.tar.gz: 23d8417049ec5aa708458063d2227ef7825a62f8e54b44c64f9b083ab5f1280e
5
5
  SHA512:
6
- metadata.gz: '08bd4767c9a37ef218fd9c3448ed54481dea420ae51af0b5b11ba5cafa606b5ca960d89ffa31f762b597333baa047386c5c213cf672b43f877389efe4cf0253a'
7
- data.tar.gz: f4762978b2679a85db1b5791b83067bbade6900d8a253a2a24438bf3bce6f8599e682cca7e1ce72fdab9482b2a3fd665e06486542c5145843e2b7d57278c30ce
6
+ metadata.gz: ebaff298730cb4acbeaff6adf2e92fb6ed31471ba178e5b50ffeff410a6cb92bcec683d1bed824ec143dd550897825eecea8f280b2f34565cf00e4d989ff1409
7
+ data.tar.gz: f30372920b56840936cb5cb4bdfc29360fde15421480605ec6cbec4c2cfb5eaa74e495dad983d1bfa37cbf72b3b2e522a663ae6b8e7b48a6c43e63341713a740
data/Rakefile CHANGED
@@ -1,13 +1,17 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'bundler/gem_tasks'
4
- require 'minitest/test_task'
5
-
6
- Minitest::TestTask.create # rubocop:disable Rails/SaveBang
7
-
4
+ require 'rake/testtask'
8
5
  require 'rubocop/rake_task'
9
6
 
10
7
  RuboCop::RakeTask.new
11
8
 
9
+ Rake::TestTask.new(:test) do |t|
10
+ t.libs << 'test'
11
+ t.pattern = 'test/**/*_test.rb'
12
+ t.verbose = false
13
+ t.warning = false
14
+ end
15
+
12
16
  task static: :rubocop
13
17
  task default: %i[static test]
@@ -23,9 +23,9 @@ module ActiveRecordConnectionReaper
23
23
  duration * (1.0 - @pool_jitter)
24
24
  end
25
25
 
26
- MAX_JITTER = 0.0..1.0
26
+ MAX_JITTER = 1.0
27
27
  def max_jitter
28
- (@config[:pool_jitter] || 0.2).to_f.clamp(MAX_JITTER)
28
+ (@config[:pool_jitter] || 0.2).to_f.clamp(0.0, MAX_JITTER)
29
29
  end
30
30
  end
31
31
  end
@@ -28,6 +28,10 @@ module ActiveRecordConnectionReaper
28
28
 
29
29
  old_connections.each(&:disconnect!)
30
30
  end
31
+
32
+ def __patched_discarded?
33
+ @connections.nil?
34
+ end
31
35
  end
32
36
  end
33
37
  end
@@ -1,24 +1,65 @@
1
+ require 'weakref'
2
+
1
3
  module ActiveRecordConnectionReaper
2
4
  module Extensions
3
5
  module ActiveRecord
4
6
  module ConnectionAdapters
5
7
  module ReaperCheckMaxAge
6
- def run
7
- return unless frequency&.positive?
8
- Thread.new(frequency, pool) do |t, p|
9
- loop do
10
- sleep t
11
- run_once(p)
8
+ def self.prepended(base)
9
+ base.instance_variable_set(:@mutex, Mutex.new) if base.instance_variable_get(:@mutex).nil?
10
+ base.instance_variable_set(:@pools, {}) if base.instance_variable_get(:@pools).nil?
11
+ base.instance_variable_set(:@threads, {}) if base.instance_variable_get(:@threads).nil?
12
+
13
+ base.singleton_class.send(:prepend, ClassMethods)
14
+ end
15
+
16
+ module ClassMethods
17
+ def __patched_register_pool(pool, frequency) # :nodoc:
18
+ @mutex.synchronize do
19
+ @threads[frequency] = __patched_spawn_thread(frequency) unless @threads[frequency]&.alive?
20
+ @pools[frequency] ||= []
21
+ @pools[frequency] << WeakRef.new(pool)
12
22
  end
13
23
  end
14
- end
15
24
 
16
- private
25
+ private
26
+
27
+ def __patched_spawn_thread(frequency) # rubocop:disable Metrics/MethodLength
28
+ Thread.new(frequency) do |t|
29
+ # Advise multi-threaded app servers to ignore this thread for
30
+ # the purposes of fork safety warnings
31
+ Thread.current.thread_variable_set(:fork_safe, true)
32
+ Thread.current.name = 'AR Pool Reaper'
33
+ running = true
34
+ while running
35
+ sleep t
36
+ @mutex.synchronize do
37
+ @pools[frequency].select! do |pool|
38
+ pool.weakref_alive? && !pool.__patched_discarded?
39
+ end
17
40
 
18
- def run_once(pool)
19
- pool.reap
20
- pool.flush
21
- pool.retire_old_connections
41
+ @pools[frequency].each do |p|
42
+ p.reap
43
+ p.flush
44
+ p.retire_old_connections
45
+ rescue WeakRef::RefError
46
+ # Pool has been garbage collected. Nothing we can do here, move on.
47
+ end
48
+
49
+ if @pools[frequency].empty?
50
+ @pools.delete(frequency)
51
+ @threads.delete(frequency)
52
+ running = false
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
59
+
60
+ def run
61
+ return unless frequency&.positive?
62
+ self.class.__patched_register_pool(pool, frequency)
22
63
  end
23
64
  end
24
65
  end
@@ -9,9 +9,9 @@ module ActiveRecordConnectionReaper
9
9
  require 'activerecord_connection_reaper/extensions/active_record/connection_adapters/reaper_check_max_age'
10
10
  require 'activerecord_connection_reaper/extensions/active_record/connection_adapters/pool_max_age'
11
11
 
12
- ActiveRecord::ConnectionAdapters::AbstractAdapter.prepend(ActiveRecordConnectionReaper::Extensions::ActiveRecord::ConnectionAdapters::AbstractAdapterTrackConnectedSince)
13
- ActiveRecord::ConnectionAdapters::ConnectionPool::Reaper.prepend(ActiveRecordConnectionReaper::Extensions::ActiveRecord::ConnectionAdapters::ReaperCheckMaxAge)
14
- ActiveRecord::ConnectionAdapters::ConnectionPool.prepend(ActiveRecordConnectionReaper::Extensions::ActiveRecord::ConnectionAdapters::PoolMaxAge)
12
+ ActiveRecord::ConnectionAdapters::AbstractAdapter.prepend(ActiveRecordConnectionReaper::Extensions::ActiveRecord::ConnectionAdapters::AbstractAdapterTrackConnectedSince) # rubocop:disable Layout/LineLength
13
+ ActiveRecord::ConnectionAdapters::ConnectionPool::Reaper.prepend(ActiveRecordConnectionReaper::Extensions::ActiveRecord::ConnectionAdapters::ReaperCheckMaxAge) # rubocop:disable Layout/LineLength
14
+ ActiveRecord::ConnectionAdapters::ConnectionPool.prepend(ActiveRecordConnectionReaper::Extensions::ActiveRecord::ConnectionAdapters::PoolMaxAge) # rubocop:disable Layout/LineLength
15
15
  end
16
16
  end
17
17
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ActiveRecordConnectionReaper
4
- VERSION = '0.2.0'
4
+ VERSION = '0.4.0'
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: activerecord_connection_reaper
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Miriam Technologies
@@ -77,9 +77,12 @@ require_paths:
77
77
  - lib
78
78
  required_ruby_version: !ruby/object:Gem::Requirement
79
79
  requirements:
80
- - - "~>"
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '2.5'
83
+ - - "<"
81
84
  - !ruby/object:Gem::Version
82
- version: 3.4.0
85
+ version: '3.5'
83
86
  required_rubygems_version: !ruby/object:Gem::Requirement
84
87
  requirements:
85
88
  - - ">="