ruby-on-railsrubyactiverecordsinatrasinatra-activerecord

Replacing ActiveRecord::ConnectionAdapters::ConnectionManagement in ActiveRecord 5


We are upgrading a Sinatra application from ActiveRecord 4 to ActiveRecord 5. Previously we had this line:

use ActiveRecord::ConnectionAdapters::ConnectionManagement

This is because connections were not being cleaned up after requests completed. Here is prior SO discussion on this topic:

Starting with ActiveRecord 5, this line no longer works. This conversation in the rails project states:

This was removed in favor of Executor and Reloader APIs. That middleware that was removed were not part of the public API. If you want to use that outside Rails you need to make one.

Does this mean that, if someone is to use ActiveRecord 5 with Sinatra, connections will be again 'leaked' or left un-returned to the pool after a request, unless the developer re-creates the now-removed middleware?

In the Sinatra example, is it therefore now the case that we need to include this line in ActiveRecord 5?

after do
  ActiveRecord::Base.clear_active_connections!
end

That is the implication on the linked-to thread, but I want to get a definite answer I can take back to my dev team.


Solution

  • You are correct, the ConnectionManagement middleware has been removed from ActiveRecord 5 (PR #23807), so you will need to replicate similar functionality when setting up ActiveRecord outside of Rails. There are several ways to do this:

    1. ConnectionManagement Rack middleware

    The ConnectionManagement class is not very complicated. You can copy and paste the implementation somewhere in your local application, and include it as usual into your Rack middleware stack:

    class ConnectionManagement
      def initialize(app)
        @app = app
      end
    
      def call(env)
        testing = env['rack.test']
    
        status, headers, body = @app.call(env)
        proxy = ::Rack::BodyProxy.new(body) do
          ActiveRecord::Base.clear_active_connections! unless testing
        end
        [status, headers, proxy]
      rescue Exception
        ActiveRecord::Base.clear_active_connections! unless testing
        raise
      end
    end
    
    use ConnectionManagement
    

    2. (Sinatra-specific) connection-management after hook

    Within a Sinatra app, the block you suggested should work:

    after do
      ActiveRecord::Base.clear_active_connections!
    end
    

    Note that this is also the approach currently used by the sinatra-activerecord integration gem to support ActiveRecord 5 (see issue #73).

    3. ActionDispatch::Executor Rack middleware

    Finally, you can use the same code Rails is now using for ActiveRecord connection management by adding ActionDispatch::Executor into your Rack middleware stack, and calling ActiveRecord::QueryCache#install_executor_hooks to insert the hook used to clear ActiveRecord connections:

    require 'action_dispatch/middleware/executor'
    use ActionDispatch::Executor, ActiveSupport::Executor
    ActiveRecord::QueryCache.install_executor_hooks