<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>oslivan-github (Justin)</title>
    <link>https://ruby-china.org/oslivan-github</link>
    <description></description>
    <language>en-us</language>
    <item>
      <title>在 Grape 中使用 Rails6 的 ConnectionManagement 管理</title>
      <description>&lt;h3 id="Rails 5 之前"&gt;Rails 5 之前&lt;/h3&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;#...&lt;/span&gt;
&lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Rack&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;app&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;use&lt;/span&gt; &lt;span class="no"&gt;ActiveRecord&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;ConnectionAdapters&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;ConnectionManagement&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="n"&gt;run&lt;/span&gt; &lt;span class="n"&gt;app&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id="Rails5 之后（使用了 QueryCache 方式）"&gt;Rails5 之后（使用了 QueryCache 方式）&lt;/h3&gt;&lt;h5 id="方法一：直接使用 Rails 原生方式"&gt;方法一：直接使用 Rails 原生方式&lt;/h5&gt;
&lt;ul&gt;
&lt;li&gt;config.ru&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;#...&lt;/span&gt;
&lt;span class="nb"&gt;require_relative&lt;/span&gt; &lt;span class="s1"&gt;'config/environment'&lt;/span&gt;
&lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Rack&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;app&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;run&lt;/span&gt; &lt;span class="no"&gt;Resources&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Index&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="c1"&gt;# 处理连接的配置&lt;/span&gt;
&lt;span class="n"&gt;exe&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;ActiveSupport&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Executor&lt;/span&gt;
&lt;span class="no"&gt;ActiveRecord&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;QueryCache&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;install_executor_hooks&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;exe&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;run&lt;/span&gt; &lt;span class="nb"&gt;lambda&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;exe&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;wrap&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;config/environment.rb &lt;/li&gt;
&lt;/ul&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# 其他需要加载/初始化的动作&lt;/span&gt;

&lt;span class="c1"&gt;# 下面这几行很关键，因为在非 Rails 应用中，启动时不会自动初始化 `connection_handlers`，然而 ActiveRecord::QueryCache 中有&lt;/span&gt;
&lt;span class="c1"&gt;# 使用到了，对于 Rails 中的 `connection_management_test.rb` 之所以能跑通，是因为在 `activerecord/test/cases/helper.rb` 中调&lt;/span&gt;
&lt;span class="c1"&gt;# 用了 `ARTest.connect`，而这个方法里面明确的初始化了 `connection_handlers`&lt;/span&gt;
&lt;span class="no"&gt;ActiveRecord&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Base&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;class_eval&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;connection_handlers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;writing_role&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;default_connection_handler&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;h5 id="方法二：使用 otr-activerecord 包"&gt;方法二：使用 otr-activerecord 包&lt;/h5&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#...&lt;/span&gt;
app &lt;span class="o"&gt;=&lt;/span&gt; Rack::Builder.app &lt;span class="k"&gt;do
  &lt;/span&gt;use OTR::ActiveRecord::ConnectionManagement
end
run app
&lt;/code&gt;&lt;/pre&gt;&lt;h5 id="方法三：直接自己定义一个 middleware 来执行清理"&gt;方法三：直接自己定义一个 middleware 来执行清理&lt;/h5&gt;
&lt;p&gt;没有尝试&lt;/p&gt;
&lt;h3 id="测试验证"&gt;测试验证&lt;/h3&gt;
&lt;p&gt;假如每次请求返回都是 false，表示清理成功了&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# config.ru&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;TestConnectionManagement&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;initialize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="vi"&gt;@app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;app&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="no"&gt;ActiveRecord&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Base&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;connection_handler&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;active_connections?&lt;/span&gt;
    &lt;span class="vi"&gt;@app.call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Rack&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;app&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;use&lt;/span&gt; &lt;span class="no"&gt;TestConnectionManagement&lt;/span&gt;
  &lt;span class="c1"&gt;# ...&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="c1"&gt;# ...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id="总结"&gt;总结&lt;/h3&gt;
&lt;p&gt;我是用 Rails 6 测试的，但是 &lt;code&gt;ActiveRecord::ConnectionAdapters::ConnectionManagement&lt;/code&gt; 在 Rails 5 就移除了，所以使用方式可能有些差异，比如可能 Rails5 中不需要自己去初始化 &lt;code&gt;connection_handlers&lt;/code&gt;，源码没去细看了，如果用 Rails 5 的可以先试着不初始化 &lt;code&gt;connection_handlers&lt;/code&gt;，看看结果怎么样。&lt;/p&gt;
&lt;h3 id="参考"&gt;参考&lt;/h3&gt;
&lt;p&gt;&lt;a href="https://github.com/jhollinger/otr-activerecord" rel="nofollow" target="_blank" title=""&gt;https://github.com/jhollinger/otr-activerecord&lt;/a&gt;&lt;br&gt;
&lt;a href="https://stackoverflow.com/questions/41400202/replacing-activerecordconnectionadaptersconnectionmanagement-in-activerecord" rel="nofollow" target="_blank" title=""&gt;https://stackoverflow.com/questions/41400202/replacing-activerecordconnectionadaptersconnectionmanagement-in-activerecord&lt;/a&gt;&lt;br&gt;
&lt;a href="https://github.com/jhollinger/otr-activerecord" rel="nofollow" target="_blank" title=""&gt;https://github.com/jhollinger/otr-activerecord&lt;/a&gt;  &lt;/p&gt;</description>
      <author>oslivan-github</author>
      <pubDate>Thu, 14 Jan 2021 12:54:21 +0800</pubDate>
      <link>https://ruby-china.org/topics/40806</link>
      <guid>https://ruby-china.org/topics/40806</guid>
    </item>
  </channel>
</rss>
