ActiveRecord Preconnect

This library adds the preconnect! method to ActiveRecord::ConnectionAdapters::ConnectionPool. Use this when you want all of your connections in your connection pool to eagerly connect to the database, rather than lazily.

Why

When using Postgres on Heroku with PGBouncer you can run into situations where your process will hang indefinitely. This issue occurs when using ActiveRecord, Sequel and potentially other database mappers.

The solution in Sequel is to set the preconnect option to true. This option tells Sequel to open all database connection eagerly, rather than lazily, and avoids potential deadlocks. I couldn't find an equivalent option in ActiveRecord so I wrote this small library to provide a method to do so.

Installation

Add this line to your application's Gemfile:

gem "ar_preconnect"

Usage

With Sidekiq:

# ./config/initializers/sidekiq.rb
Sidekiq.configure_server do |config|
  ActiveRecord::Base.connection.pool.preconnect!
end

With Passenger in cluster-mode.

# ./config/initializers/passenger.rb
if defined?(PhusionPassenger)
  PhusionPassenger.on_event(:starting_worker_process) do |forked|
    if forked
      ActiveRecord::Base.establish_connection
      ActiveRecord::Base.connection.pool.preconnect!
    end
  end
end

With Unicorn in cluster-mode.

# ./config/initializers/unicorn.rb
before_fork do |server, worker|
  ActiveRecord::Base.connection.disconnect!
end

after_fork do |server, worker|
  ActiveRecord::Base.establish_connection
  ActiveRecord::Base.connection.pool.preconnect!
end

With Puma in cluster-mode.

# ./config/initializers/puma.rb
on_worker_boot do
  ActiveSupport.on_load(:active_record) do
    ActiveRecord::Base.establish_connection
    ActiveRecord::Base.connection.pool.preconnect!
  end
end

With Clockwork:

# ./clock.rb
require "clockwork"
require_relative "config/boot"
require_relative "config/environment"

ActiveRecord::Base.connection.pool.preconnect!

module Clockwork
  every(1.minute, "do something") do
    MyWorker.perform_async
  end
end

Verify

Verify that this works:

pool = ActiveRecord::Base.connection.pool

puts "#{pool.connections.count} connections established."
pool.preconnect!
puts "#{pool.connections.count} connections established."

Author / License

Released under the MIT License by Michael van Rooijen.