I have a small rails app that spawns new threads to update itself in the background until a certain condition is met.
class SomeModel < ApplicationRecord
def self.some_action
if some_condition
Thread.new do
begin
sleep some_arbitrary_time
ActiveRecord::Base.connection_pool.with_connection do
update(attr_x: true)
some_action
end
ensure
ActiveRecord::Base.connection_pool.release_connection
end
end
end
end
end
I have tried ActiveRecord::with_connection
releasing
closing
connections, but in the end, there are always idle connections.
Checking the db or ActiveRecord show several idle connections
db_development=# select state from pg_stat_activity where pid <> pg_backend_pid();
state
-------
idle
idle
idle
idle
ActiveRecord::Base.connection_pool.stat
{"size":10,"connections":5,"busy":1,"dead":0,"idle":4,"waiting":0,"checkout_timeout":5}
It is my understanding that the reaping
process only takes care of dead connections, idle connections will stay there consuming pool resources.
A more simple example (based of a particular rails issue) shows that there are idle processes after the use of new Threads and with_connection
.
Before the test
collab-playlist_development=# select state from pg_stat_activity where pid <> pg_backend_pid();
state
-------
(0 rows)
20.times.map do
Thread.new do
ActiveRecord::Base.connection_pool.with_connection do
SomeModel.count
end
end
end
After the test
db_development=# select state from pg_stat_activity where pid <> pg_backend_pid();
state
-------
idle
idle
idle
idle
idle
idle
idle
idle
idle
idle
ActiveRecord::Base.connection_pool.stat
{"size":10,"connections":10,"busy":0,"dead":0,"idle":10,"waiting":0,"checkout_timeout":5}
Is there a way to close those idle connections to free up pool resources?
Some references (aside from the rails doc) that shed some light into this issue, but no resolution:
SO
- How to manage opening and closing database connections while working with activerecords and multiple threads
- Connection pool issue with ActiveRecord objects in rufus-scheduler
Blog posts