Skip to content

Instantly share code, notes, and snippets.

@cris
Created May 11, 2012 09:48
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save cris/2658680 to your computer and use it in GitHub Desktop.
Save cris/2658680 to your computer and use it in GitHub Desktop.
Fix for broken connection-pool in Rails < 3.3.0
# Monkey patch ConnectionPool#checkout to avoid database connection timeouts
# Source: https://github.com/rails/rails/issues/2547
# For Rails 3.2.0 and upper, You need to check if the pool error still occurs
if Rails.version < "3.3.0"
class ActiveRecord::ConnectionAdapters::ConnectionPool
def checkout
# Checkout an available connection
start_at = Time.now
@connection_mutex.synchronize do
loop do
conn = try_to_obtain_connection
return conn if conn
should_not_be_timeout!(start_at)
# No connections available; wait for one
is_timeout = !@queue.wait(@timeout) # mutex is lost
# mutex is obtained again
if is_timeout
# try looting dead threads
clear_stale_cached_connections!
raise_timeout_error! unless can_obtain_connection?
end
end
end
end
synchronize :connection, :release_connection, :clear_stale_cached_connections!, :with => :@connection_mutex
private
def can_obtain_connection?
@size > @checked_out.size
end
def should_not_be_timeout!(start_at)
return if (Time.now - start_at) < @timeout
raise_timeout_error!
end
def try_to_obtain_connection
if @checked_out.size < @connections.size
checkout_existing_connection
elsif @connections.size < @size
checkout_new_connection
end
end
def raise_timeout_error!
raise ActiveRecord::ConnectionTimeoutError, "could not obtain a database connection#{" within #{@timeout} seconds" if @timeout}. The max pool size is currently #{@size}; consider increasing it."
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment