在ActiveRecord 5中替换ActiveRecord::ConnectionAdapters::ConnectionManagement

15

我们正在将一个Sinatra应用程序从ActiveRecord 4升级到ActiveRecord 5。以前我们有这样一行代码:

use ActiveRecord::ConnectionAdapters::ConnectionManagement

这是因为连接在请求完成后没有被清理干净。以下是此主题的先前SO讨论:

从ActiveRecord 5开始,这行代码不再起作用。这个Rails项目中的讨论表明:

这已被Executor和Reloader APIs所代替。那些被移除的中间件不是公共API的一部分。如果你想在Rails之外使用它,你需要创建一个。
这是否意味着,如果有人要在Sinatra中使用ActiveRecord 5,连接将再次在请求后泄漏或未返回到池中,除非开发者重新创建现已删除的中间件?
因此,在Sinatra示例中,我们现在需要在ActiveRecord 5中包含这行代码吗?
after do
  ActiveRecord::Base.clear_active_connections!
end

这是对链接线程的暗示,但我希望得到一个明确的答案,以便将其带回给我的开发团队。


你找到答案了吗? - dortzur
我没有这么做;我们将继续按照上述方式调用AR5中的该行。 - esilver
1个回答

16

您是正确的,ConnectionManagement 中间件已从 ActiveRecord 5 中移除(PR #23807),因此您需要在设置 ActiveRecord 在 Rails 之外时复制类似的功能。有几种方法可以实现:

1. ConnectionManagement Rack 中间件

ConnectionManagement 并不是非常复杂。您可以将其实现复制粘贴到本地应用程序的某个位置,并像往常一样将其包含在 Rack 中间件堆栈中:

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特定)连接管理after钩子

在Sinatra应用程序中,您建议的块应该有效:

after do
  ActiveRecord::Base.clear_active_connections!
end

请注意,这也是目前被使用的方法,用于支持ActiveRecord 5的sinatra-activerecord集成宝石 (参见问题#73)。

3. ActionDispatch::Executor Rack中间件

最后,您可以通过将ActionDispatch::Executor添加到Rack中间件堆栈中,并调用ActiveRecord :: QueryCache#install_executor_hooks 插入用于清除ActiveRecord连接的钩子,使用与Rails现在正在使用的相同的代码来管理ActiveRecord连接。

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

哇哦,非常感谢您提供详细而明确的答案! - esilver
2
我已经在这个宝石中封装了class ConnectionManagement:https://github.com/ioquatix/activerecord-rack - ioquatix
@KMRakibulIslam 这个问题是关于如何在 非 Rails 环境(更具体地说是 Sinatra)中使用 ActiveRecord 5;由于 ActiveRecord 连接管理已经内置到 Rails 中,因此在这种情况下不需要额外的代码。 - wjordan
这里不是讨论无关的Rails连接池问题的地方 - 请将其单独发布到StackOverflow上,也许会有人帮助您回答。 - wjordan
在ActiveRecord 6中,为了使查询缓存正常工作,我还需要在establish_connection之前添加以下代码:ActiveRecord::Base.connection_handlers = { writing: ActiveRecord::Base.default_connection_handler } - basex

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接