Rails, Sidekiq, and the Database Connection Pool
Update: The creator of Sidekiq, Mike Perham, quickly and correctly pointed out that standard ActiveRecord use inside Sidekiq should include automatic connection pool checkins when jobs are complete.
I failed to realize that using ActiveRecord::Base.connection checks out a connection from the pool but does not automatically return it at the end of each job / web request. Never fully trusting AR to make the most efficient or performant choices (for our use cases, anyway) when generating SQL, we use this all over the codebase.
The Rails database.yml configuration option idle_timeout
should also probably be reduced from the default of 300 seconds to something more reasonable for your needs. We are starting with 60.
The solution described below remains a solution, but the better long-term fix is to instead use ActiveRecord::Base.with_connection.
If you access your database in non-standard ways inside a Rails app, you must manually release the connection back into the connection pool. This is easily accomplished by calling ActiveRecord::Base.clear_active_connections!().
To make this easy, write a Sidekiq Server Middleware that does it automatically.
class MysqlConnectionPoolMiddleware
def call(worker, job, queue)
begin
ActiveRecord::Base.clear_active_connections!()
rescue => e
puts(e.message)
end
begin
yield
rescue => e
puts(e.message)
end
end
end
Sidekiq.configure_server do |config|
config.server_middleware do |chain|
chain.add(MysqlConnectionPoolMiddleware)
end
end
Place that in config/initializers/sidekiq.rb
and blow a kiss to your database.