06b035f2ea
This fixes the "can't create Thread: Resource temporarily unavailable" error.
98 lines
2.5 KiB
Ruby
98 lines
2.5 KiB
Ruby
raise "Remove no-longer-needed #{__FILE__}!" if Rails::VERSION::MAJOR >= 6
|
|
|
|
require "weakref"
|
|
|
|
module ActiveRecord
|
|
# Backport https://github.com/rails/rails/pull/36998 and https://github.com/rails/rails/pull/36999
|
|
# to avoid `ThreadError: can't create Thread: Resource temporarily unavailable` issues
|
|
module ConnectionAdapters
|
|
class ConnectionPool
|
|
class Reaper
|
|
@mutex = Mutex.new
|
|
@pools = {}
|
|
@threads = {}
|
|
|
|
class << self
|
|
def register_pool(pool, frequency) # :nodoc:
|
|
@mutex.synchronize do
|
|
unless @threads[frequency]&.alive?
|
|
@threads[frequency] = spawn_thread(frequency)
|
|
end
|
|
@pools[frequency] ||= []
|
|
@pools[frequency] << WeakRef.new(pool)
|
|
end
|
|
end
|
|
|
|
private
|
|
|
|
def spawn_thread(frequency)
|
|
Thread.new(frequency) do |t|
|
|
running = true
|
|
while running
|
|
sleep t
|
|
@mutex.synchronize do
|
|
@pools[frequency].select!(&:weakref_alive?)
|
|
@pools[frequency].each do |p|
|
|
p.reap
|
|
p.flush
|
|
rescue WeakRef::RefError
|
|
end
|
|
|
|
if @pools[frequency].empty?
|
|
@pools.delete(frequency)
|
|
@threads.delete(frequency)
|
|
running = false
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
def run
|
|
return unless frequency && frequency > 0
|
|
|
|
self.class.register_pool(pool, frequency)
|
|
end
|
|
end
|
|
|
|
def reap
|
|
stale_connections = synchronize do
|
|
return unless @connections
|
|
|
|
@connections.select do |conn|
|
|
conn.in_use? && !conn.owner.alive?
|
|
end.each(&:steal!)
|
|
end
|
|
|
|
stale_connections.each do |conn|
|
|
if conn.active?
|
|
conn.reset!
|
|
checkin conn
|
|
else
|
|
remove conn
|
|
end
|
|
end
|
|
end
|
|
|
|
def flush(minimum_idle = @idle_timeout)
|
|
return if minimum_idle.nil?
|
|
|
|
idle_connections = synchronize do
|
|
return unless @connections
|
|
|
|
@connections.select do |conn|
|
|
!conn.in_use? && conn.seconds_idle >= minimum_idle
|
|
end.each do |conn|
|
|
conn.lease
|
|
|
|
@available.delete conn
|
|
@connections.delete conn
|
|
end
|
|
end
|
|
|
|
idle_connections.each(&:disconnect!)
|
|
end
|
|
end
|
|
end
|
|
end
|