# This hack is designed to prevent a thread from implicitly checking out an AR connection by | |
# just accessing ActiveRecord::Base.connection. The point of doing this is to ensure that threads | |
# don't tie up connections that they are not using, by making sure we're explicit about where we | |
# need to use an AR connection. | |
# | |
# See also http://tenderlovemaking.com/2011/10/20/connection-management-in-activerecord.html | |
ActiveSupport.on_load(:active_record) do | |
ActiveRecord::ConnectionAdapters::ConnectionPool # ensure loaded | |
if ActiveRecord::VERSION::STRING !~ /^4.0/ | |
raise "This hack was written for Active Record 4.0. It needs to be checked " \ | |
"in order to use it with #{ActiveRecord::VERSION::STRING}." | |
end | |
module ActiveRecord | |
class ImplicitConnectionDisabled < ConnectionNotEstablished | |
end | |
module DisableImplicitConnection | |
def connection | |
if conn = @reserved_connections[current_connection_id] | |
conn | |
else | |
if Thread.current[:allow_implicit_connection] | |
reserve_connection | |
else | |
raise ImplicitConnectionDisabled | |
end | |
end | |
end | |
def reserve_connection | |
synchronize do | |
@reserved_connections[current_connection_id] ||= checkout | |
end | |
end | |
def allow_implicit_connection | |
Thread.current[:allow_implicit_connection] | |
end | |
def allow_implicit_connection=(val) | |
Thread.current[:allow_implicit_connection] = val | |
end | |
def with_connection | |
prev, self.allow_implicit_connection = self.allow_implicit_connection, true | |
super { |c| yield c } | |
ensure | |
self.allow_implicit_connection = prev | |
end | |
end | |
module ReserveRackConnection | |
def call(env) | |
ActiveRecord::Base.connection_pool.allow_implicit_connection = true | |
super | |
end | |
end | |
module ConnectionAdapters | |
class ConnectionPool | |
prepend DisableImplicitConnection | |
end | |
class ConnectionManagement | |
prepend ReserveRackConnection | |
end | |
end | |
end | |
Thread.main[:allow_implicit_connection] = true | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment