<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>lithium4010 (屎丸)</title>
    <link>https://ruby-china.org/lithium4010</link>
    <description></description>
    <language>en-us</language>
    <item>
      <title>KMP next 数组构建的理解</title>
      <description>&lt;p&gt;研究这个的动机是因为 &lt;a href="https://leetcode.com/problems/longest-happy-prefix/" rel="nofollow" target="_blank"&gt;https://leetcode.com/problems/longest-happy-prefix/&lt;/a&gt; 这个周赛题不会&lt;/p&gt;

&lt;p&gt;然后看了很多网上讲解 KMP 的博客，发现还是不理解。
因为很多到了求“最长相等前后缀”这一步就略过了或者讲的不好理解。&lt;/p&gt;

&lt;p&gt;这里 &lt;code&gt;next[i]&lt;/code&gt; 等于 &lt;code&gt;s[0..i]&lt;/code&gt; 这个子串的最长相等前后缀。
目的是希望根据 &lt;code&gt;next[0..i]&lt;/code&gt; 和 &lt;code&gt;s[0..i+1]&lt;/code&gt; 求 &lt;code&gt;next[i+1]&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;因为 &lt;code&gt;s[0...next[i]] == s[(i-next[i]+1)..i]&lt;/code&gt;，所以当 &lt;code&gt;s[next[i]] == s[i+1]&lt;/code&gt; 的时候，我们找到了&lt;code&gt;匹配&lt;/code&gt;，有 &lt;code&gt;next[i+1] = next[i] + 1&lt;/code&gt; 。&lt;/p&gt;

&lt;p&gt;比如 &lt;code&gt;"ccbccc"&lt;/code&gt; 这个字符串有 &lt;code&gt;next = [0, 1, 0, 1, 2, 2]&lt;/code&gt;，考察 &lt;code&gt;i = 3&lt;/code&gt; 时，&lt;code&gt;next[3] == 1, s[1] == 'c' == s[4]&lt;/code&gt;，所以 &lt;code&gt;next[4] = next[3] + 1 = 2&lt;/code&gt;。&lt;/p&gt;

&lt;p&gt;难点是如果 &lt;code&gt;s[next[i]] != s[i+1]&lt;/code&gt;，应该如何计算 &lt;code&gt;next[i+1]&lt;/code&gt;。
首先显然 &lt;code&gt;next[i+1]&lt;/code&gt; 会小于等于 &lt;code&gt;next[i]&lt;/code&gt;。即如果有匹配，&lt;code&gt;s[i+1]&lt;/code&gt; 会匹配上 &lt;code&gt;s[0...next[i]]&lt;/code&gt; 之间的某一个字符，也就是&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;匹配的位置会向前移动
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;问题是移到哪个位置 &lt;code&gt;j&lt;/code&gt;，可以确保 &lt;code&gt;s[0...j] == s[(i-j+1)..i]&lt;/code&gt; 且 &lt;code&gt;j&lt;/code&gt; 最大，这样可以再次通过比较 &lt;code&gt;s[j]&lt;/code&gt; 和 &lt;code&gt;s[i+1]&lt;/code&gt; 来确定 &lt;code&gt;next[i+1]&lt;/code&gt; 的值。&lt;/p&gt;

&lt;p&gt;&lt;code&gt;s[0...j]&lt;/code&gt; 是 &lt;code&gt;s[0..i]&lt;/code&gt; 的一个前缀，&lt;code&gt;s[(i-j+1)..i]&lt;/code&gt; 是 &lt;code&gt;s[0..i]&lt;/code&gt; 的一个后缀，且满足 &lt;code&gt;s[0...j] == s[(i-j+1)..i]&lt;/code&gt;，&lt;code&gt;j &amp;lt; next[i]&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;换句话说，我希望找到&lt;code&gt;s[0..i]&lt;/code&gt;的一个第二长的相等前后缀来尝试匹配，如果不匹配，就尝试找第三长的，最后可能和 &lt;code&gt;s&lt;/code&gt; 的第一个字符比较。&lt;/p&gt;

&lt;p&gt;&lt;code&gt;s[0..i]&lt;/code&gt;最长的相等前后缀长度是 &lt;code&gt;next[i]&lt;/code&gt;，次长是什么呢？&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;应该是 s[0...next[i]] 的最长相等前后缀的长度
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;代换一下变量，&lt;code&gt;s[0...next[i]] == s[0..(next[i] - 1)]&lt;/code&gt; =&amp;gt; 次长为 &lt;code&gt;next[next[i] - 1]&lt;/code&gt; =&amp;gt; &lt;code&gt;j = next[next[i] - 1]&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;第三长的为 &lt;code&gt;s[0...next[next[i] - 1]]&lt;/code&gt; 的最长相等前后缀的长度&lt;/p&gt;

&lt;p&gt;以此类推 &lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;j = next[next[i] - 1] // 第二长
j = next[j - 1]  // 第三长
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;比如 &lt;code&gt;"ccbccc"&lt;/code&gt; 这个字符串有 &lt;code&gt;next = [0, 1, 0, 1, 2, 2]&lt;/code&gt;，考察 &lt;code&gt;i = 4&lt;/code&gt; 时，&lt;code&gt;next[4] == 2, s[2] == 'b' != s[5]&lt;/code&gt;，这时尝试检查 &lt;code&gt;j = next[next[4] - 1] = next[1] = 1&lt;/code&gt; 位置 &lt;code&gt;s[j] = s[1] = 'c' = s[i + 1]&lt;/code&gt;，匹配成功，&lt;code&gt;next[5] = j + 1 = 1 + 1 = 2&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;最后贴一段代码&lt;/p&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;impl&lt;/span&gt; &lt;span class="n"&gt;Solution&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;longest_prefix&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;cs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Vec&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;char&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="nf"&gt;.chars&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.collect&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;next&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nd"&gt;vec!&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="nf"&gt;.len&lt;/span&gt;&lt;span class="p"&gt;()];&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="nf"&gt;.len&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="c1"&gt;// find match&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;cs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;next&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;cs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;next&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;next&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                &lt;span class="k"&gt;continue&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;

            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;next&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;continue&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

            &lt;span class="c1"&gt;// not find, decrease j to try match&lt;/span&gt;
            &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;next&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;next&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
            &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;cs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;cs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="n"&gt;next&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;    
                    &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt;

                &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

                &lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;next&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&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;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="n"&gt;next&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="nf"&gt;.len&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]]&lt;/span&gt;&lt;span class="nf"&gt;.to_string&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;</description>
      <author>lithium4010</author>
      <pubDate>Mon, 23 Mar 2020 22:30:05 +0800</pubDate>
      <link>https://ruby-china.org/topics/39651</link>
      <guid>https://ruby-china.org/topics/39651</guid>
    </item>
    <item>
      <title>QA 不写测试用例，大家怎么看？</title>
      <description>&lt;p&gt;小团队十来个人，一个 QA，女。工作认真负责。就是不写测试用例，认为增量测试就可以了，写用例浪费时间，怎么破？&lt;/p&gt;</description>
      <author>lithium4010</author>
      <pubDate>Fri, 27 Jul 2018 22:51:58 +0800</pubDate>
      <link>https://ruby-china.org/topics/37240</link>
      <guid>https://ruby-china.org/topics/37240</guid>
    </item>
    <item>
      <title>推荐大家使用 ruby:2.5.1-alpine 镜像 </title>
      <description>&lt;p&gt;内存超稳定，内存占用也小，墙裂推荐。&lt;/p&gt;</description>
      <author>lithium4010</author>
      <pubDate>Fri, 18 May 2018 17:59:26 +0800</pubDate>
      <link>https://ruby-china.org/topics/36799</link>
      <guid>https://ruby-china.org/topics/36799</guid>
    </item>
    <item>
      <title>论坛里面杠精很多，有没有人有同感？</title>
      <description>&lt;p&gt;一般大家都是找喷点先喷为敬&lt;img title=":joy:" alt="😂" src="https://twemoji.ruby-china.com/2/svg/1f602.svg" class="twemoji"&gt; &lt;img title=":joy:" alt="😂" src="https://twemoji.ruby-china.com/2/svg/1f602.svg" class="twemoji"&gt; &lt;/p&gt;</description>
      <author>lithium4010</author>
      <pubDate>Sun, 29 Apr 2018 08:37:02 +0800</pubDate>
      <link>https://ruby-china.org/topics/36664</link>
      <guid>https://ruby-china.org/topics/36664</guid>
    </item>
    <item>
      <title>使用 docker-api gem 连接管理 阿里云 swarm mode 集群 </title>
      <description>&lt;p&gt;按照阿里云的&lt;a href="https://help.aliyun.com/document_detail/25983.html?spm=5176.doc26004.2.3.Oi40li" rel="nofollow" target="_blank" title=""&gt;文档&lt;/a&gt;进行操作。&lt;/p&gt;

&lt;p&gt;实测下载好证书，配置好环境变量后，可以很容易成功使用 &lt;code&gt;docker&lt;/code&gt; 命令连接到集群。&lt;/p&gt;

&lt;p&gt;在使用 &lt;a href="https://github.com/TapasTech/docker-api" rel="nofollow" target="_blank" title=""&gt;docker-api&lt;/a&gt; 连接时遇到无法连接的问题。&lt;/p&gt;

&lt;p&gt;通过查看源码，调整配置参数 &lt;code&gt;Docker.options[:debug_response] = true&lt;/code&gt;，发现 &lt;code&gt;response&lt;/code&gt; 如下：&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Excon::Error::NotAcceptable: Expected([200, 201, 202, 203, 204, 301, 304]) &amp;lt;=&amp;gt; Actual(406 Not Acceptable)
excon.error.response
  :body          =&amp;gt; "Sorry, your version is too low!\nPlease use Docker Client over 1.8, Docker REST API over 1.20.\n\n"
 .....
  :path          =&amp;gt; "/v1.16/info"
 .....
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;可以看到这里把版本锁在了 &lt;code&gt;v1.16&lt;/code&gt;
github 上搜索发现作者已经提交了一个 pr &lt;a href="https://github.com/swipely/docker-api/pull/510" rel="nofollow" target="_blank"&gt;https://github.com/swipely/docker-api/pull/510&lt;/a&gt;
fork 代码，手动 merge 他的 pr
利用 &lt;code&gt;specific_install&lt;/code&gt; 来安装到本地&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;gem install specific_install
gem specific_install -l https://github.com/xxxxx/docker-api.git
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;之后就可以正常使用 &lt;code&gt;docker-api&lt;/code&gt; 管理集群了&lt;/p&gt;

&lt;p&gt;PS：
作者应该会在之后把这个 pr 合并到 master&lt;/p&gt;</description>
      <author>lithium4010</author>
      <pubDate>Fri, 19 Jan 2018 13:45:55 +0800</pubDate>
      <link>https://ruby-china.org/topics/34917</link>
      <guid>https://ruby-china.org/topics/34917</guid>
    </item>
    <item>
      <title>Mongoid 在数据库无法访问时是否会自动重连？</title>
      <description>&lt;h2 id="生产事故"&gt;生产事故&lt;/h2&gt;
&lt;p&gt;之前生产环境发生了因为阿里云运维数据库导致所有 puma 进程以及 sidekiq 进程无法链接数据库，报错&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Mongo::Error::NoServerAvailable: No server is available matching preference
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;重启应用实例后恢复正常链接。&lt;/p&gt;
&lt;h2 id="试图复现问题"&gt;试图复现问题&lt;/h2&gt;
&lt;p&gt;起一个&lt;code&gt;rails c&lt;/code&gt; 连接生产数据库，执行以下脚本&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="kp"&gt;loop&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="k"&gt;begin&lt;/span&gt; 
    &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="no"&gt;Document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;count&lt;/span&gt;
    &lt;span class="nb"&gt;sleep&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;
  &lt;span class="k"&gt;rescue&lt;/span&gt; &lt;span class="no"&gt;Mongo&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Error&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;NoServerAvailable&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 
    &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;message&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;控制台正常输出文档数目。&lt;/p&gt;

&lt;p&gt;主机添加 iptables 规则 block 掉数据库端口的访问&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo iptables -A OUTPUT -p tcp --dport xxxxxx -j DROP
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;等待发现控制台报错&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;No server is available matching preference ...
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;恢复数据库访问&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo iptables -D OUTPUT -p tcp --dport xxxxxx -j DROP
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;等待后发现控制台恢复正常输出文档数目。&lt;/p&gt;
&lt;h2 id="求助"&gt;求助&lt;/h2&gt;
&lt;p&gt;根据上面的测试我认为 mongoid 是会自动处理数据库挂机后的重连的，那么生产事故是如何发生的？当时为何没有自动重连？&lt;/p&gt;</description>
      <author>lithium4010</author>
      <pubDate>Tue, 28 Nov 2017 15:24:11 +0800</pubDate>
      <link>https://ruby-china.org/topics/34646</link>
      <guid>https://ruby-china.org/topics/34646</guid>
    </item>
    <item>
      <title>公司同事喜欢把生产环境密码提交到 GitHub 里面怎么办？</title>
      <description>&lt;p&gt;说了很多次也不听，求助&lt;/p&gt;</description>
      <author>lithium4010</author>
      <pubDate>Tue, 04 Jul 2017 14:55:24 +0800</pubDate>
      <link>https://ruby-china.org/topics/33397</link>
      <guid>https://ruby-china.org/topics/33397</guid>
    </item>
    <item>
      <title>[转自微博 @ 网路冷眼] Rooby: a Ruby-like object oriented language written in Go</title>
      <description>&lt;p&gt;【Rooby: a Ruby-like object oriented language written in Go】&lt;a href="http://t.cn/RXpMVSt" rel="nofollow" target="_blank"&gt;http://t.cn/RXpMVSt&lt;/a&gt; Rooby：用 Go 语言编写的类 Ruby 面向对象语言。 ​&lt;/p&gt;</description>
      <author>lithium4010</author>
      <pubDate>Tue, 25 Apr 2017 07:25:03 +0800</pubDate>
      <link>https://ruby-china.org/topics/32859</link>
      <guid>https://ruby-china.org/topics/32859</guid>
    </item>
    <item>
      <title>Docker 改名了，大家怎么看？</title>
      <description>&lt;p&gt;&lt;a href="https://news.ycombinator.com/item?id=14156954" rel="nofollow" target="_blank"&gt;https://news.ycombinator.com/item?id=14156954&lt;/a&gt;&lt;/p&gt;</description>
      <author>lithium4010</author>
      <pubDate>Sun, 23 Apr 2017 21:55:39 +0800</pubDate>
      <link>https://ruby-china.org/topics/32853</link>
      <guid>https://ruby-china.org/topics/32853</guid>
    </item>
    <item>
      <title>有没有人用过 composite pattern?</title>
      <description>&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;将对象组合成树形结构以表示“整体—部分”的层次结构。Composite 模式使单个对象和组合对象的使用具有一致性&lt;/p&gt;

&lt;p&gt;这个模式在实际开发中有什么常见的应用呢？&lt;/p&gt;</description>
      <author>lithium4010</author>
      <pubDate>Thu, 09 Mar 2017 22:47:21 +0800</pubDate>
      <link>https://ruby-china.org/topics/32491</link>
      <guid>https://ruby-china.org/topics/32491</guid>
    </item>
    <item>
      <title>[BUG] 安卓客户端选择话题节点无法下拉</title>
      <description>&lt;p&gt;下拉会触发滚动刷新。&lt;/p&gt;</description>
      <author>lithium4010</author>
      <pubDate>Thu, 16 Feb 2017 22:01:05 +0800</pubDate>
      <link>https://ruby-china.org/topics/32320</link>
      <guid>https://ruby-china.org/topics/32320</guid>
    </item>
    <item>
      <title>Sidekiq 并发控制的一个小 trick</title>
      <description>&lt;p&gt;场景是 n 个耗时任务 A 需要执行，每个任务 A 之间互不影响，希望在 A 全部执行完成后开始执行某任务 B。&lt;/p&gt;

&lt;p&gt;利用 sidekiq 来并行执行 A，当并发数 q &amp;lt;&amp;lt; n 时，只需要将 n 个任务 A 和 一个任务 B 先后插入同一个 sidekiq 队列。若单个任务 A 最多耗时 t，则任务 B 执行前 sleep T，使得 T &amp;gt; t 即可。&lt;/p&gt;

&lt;p&gt;这里利用了 sidekiq 队列先进先出的特点来进行并发控制。&lt;/p&gt;

&lt;p&gt;后来想了一下，其实就是当并发数远小于任务数的时候，可以近似看做是顺序执行。Trick 在需要知道 sidekiq 实现的细节，同一队列任务确实是先进先出。&lt;/p&gt;</description>
      <author>lithium4010</author>
      <pubDate>Thu, 16 Feb 2017 21:57:23 +0800</pubDate>
      <link>https://ruby-china.org/topics/32319</link>
      <guid>https://ruby-china.org/topics/32319</guid>
    </item>
    <item>
      <title>Mina 升 1.0 后的差异</title>
      <description>&lt;p&gt;&lt;code&gt;invoke 'bundle:install'&lt;/code&gt;&lt;/p&gt;
&lt;h4 id="before 0.3.x"&gt;before 0.3.x&lt;/h4&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;echo "-----&amp;gt; Installing gem dependencies using Bundler"
    mkdir -p "/root/server/project/shared/bundle"
    mkdir -p "./vendor"
    ln -s "/root/server/project/shared/bundle" "./vendor/bundle"
    bundle install --without development:test --path "./vendor/bundle" --deployment
&lt;/code&gt;&lt;/pre&gt;&lt;h4 id="after 1.x"&gt;after 1.x&lt;/h4&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;echo "-----&amp;gt; Installing gem dependencies using Bundler" &amp;amp;&amp;amp;
  bundle install --without development test --path "vendor/bundle" --deployment
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;可以看出旧版的 bundle 会复用，而新版每次都重装一遍新的&lt;/p&gt;</description>
      <author>lithium4010</author>
      <pubDate>Wed, 18 Jan 2017 15:55:58 +0800</pubDate>
      <link>https://ruby-china.org/topics/32165</link>
      <guid>https://ruby-china.org/topics/32165</guid>
    </item>
    <item>
      <title>Sidekiq 定时任务的尝试</title>
      <description>&lt;p&gt;补充一下 crontab 是我之前用的方式，另外有同事正在使用 sidekiq_cron&lt;/p&gt;

&lt;p&gt;我觉得这两种方式都有痛点：&lt;/p&gt;
&lt;h4 id="crontab"&gt;crontab&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;和 docker 的结合不好做&lt;/li&gt;
&lt;li&gt;每次起任务都是新的进程，如果结合 rake 的话不注意会需要不少临时内存&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="sidekiq_cron"&gt;sidekiq_cron&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;相当于 monkey-patch 了 Sidekiq&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;两者都需要注意任务重复触发的问题。&lt;/p&gt;

&lt;p&gt;利用 sidekiq 自带的 perform_in &amp;amp; perform_at 实现 schedule 的问题目前我看来就是实现起来不如前面二者简便，不能直观看出系统中有哪些计划任务&lt;/p&gt;

&lt;hr&gt;

&lt;p&gt;尝试利用 sidekiq 自身的 perform_in 来实现每分钟定时任务&lt;/p&gt;

&lt;p&gt;大家是否试过这种做法，有什么样的坑？&lt;/p&gt;

&lt;p&gt;首先这个每分钟任务是可以接受初始化的时候多执行几次的，但是应该随时间快速收敛到只有一个。&lt;/p&gt;

&lt;p&gt;这个方案的好处是不管部署了多少个实例，跨了多少个服务器，任务计划总是一份。&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# initializers/schedule_seeds.rb&lt;/span&gt;

&lt;span class="no"&gt;SchedulePerMinuteWorker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;perform_async&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'sidekiq/api'&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SchedulePerMinuteWorker&lt;/span&gt;
  &lt;span class="kp"&gt;include&lt;/span&gt; &lt;span class="no"&gt;Sidekiq&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Worker&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;perform&lt;/span&gt;
    &lt;span class="c1"&gt;# 清除重复的任务计划&lt;/span&gt;
    &lt;span class="no"&gt;Sidekiq&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;ScheduledSet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;select&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;job&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;job&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;klass&lt;/span&gt; &lt;span class="o"&gt;==&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;class&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;name&lt;/span&gt; &lt;span class="p"&gt;}.&lt;/span&gt;&lt;span class="nf"&gt;each&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="ss"&gt;:delete&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;run_schedule_works&lt;/span&gt;

    &lt;span class="c1"&gt;# 结束时将自己推入&lt;/span&gt;
    &lt;span class="no"&gt;SchedulePerMinuteWorker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;perform_in&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;minute&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="c1"&gt;# 每分钟执行的任务&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;run_schedule_works&lt;/span&gt;
    &lt;span class="c1"&gt;# TODO 业务逻辑&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;hr&gt;

&lt;p&gt;我发现大部分的定时任务都不需要特别精确，能否举例一些业务场景需要用到精确的定时任务？&lt;/p&gt;</description>
      <author>lithium4010</author>
      <pubDate>Tue, 17 Jan 2017 16:47:30 +0800</pubDate>
      <link>https://ruby-china.org/topics/32154</link>
      <guid>https://ruby-china.org/topics/32154</guid>
    </item>
    <item>
      <title>Docker 的一个问题</title>
      <description>&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Error response from daemon: Driver devicemapper failed to remove root filesystem bf2c26ae5f4f341734644a2c3a5a357587604802a4ddd03a48db8251e7266d3e: Device is Busy
&lt;/code&gt;&lt;/pre&gt;
&lt;hr&gt;

&lt;p&gt;&lt;code&gt;/lib/systemd/system/docker.service&lt;/code&gt; 添加一个 Unit&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;MountFlags=slave
&lt;/code&gt;&lt;/pre&gt;</description>
      <author>lithium4010</author>
      <pubDate>Tue, 17 Jan 2017 10:35:37 +0800</pubDate>
      <link>https://ruby-china.org/topics/32149</link>
      <guid>https://ruby-china.org/topics/32149</guid>
    </item>
    <item>
      <title>redis-ruby 3.3.2 不能用</title>
      <description>&lt;p&gt;用了就各种链接超时，退回 3.3.1 就好了&lt;/p&gt;</description>
      <author>lithium4010</author>
      <pubDate>Mon, 16 Jan 2017 19:05:24 +0800</pubDate>
      <link>https://ruby-china.org/topics/32145</link>
      <guid>https://ruby-china.org/topics/32145</guid>
    </item>
    <item>
      <title>Ruby 升级到 2.4.0 后 mongoid 的问题</title>
      <description>&lt;p&gt;MRI 的 BUG，等 2.4.1&lt;/p&gt;

&lt;p&gt;&lt;a href="https://bugs.ruby-lang.org/issues/13107" rel="nofollow" target="_blank"&gt;https://bugs.ruby-lang.org/issues/13107&lt;/a&gt;&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;wrong argument type Integer (expected Proc)

/usr/local/lib/ruby/2.4.0/forwardable.rb:228:in `database'
/server/vendor/bundle/ruby/2.4.0/gems/mongo-2.4.1/lib/mongo/cursor/builder/kill_cursors_command.rb:51:in `specification'
/server/vendor/bundle/ruby/2.4.0/gems/mongo-2.4.1/lib/mongo/cursor.rb:217:in `kill_cursors_op_spec'
/server/vendor/bundle/ruby/2.4.0/gems/mongo-2.4.1/lib/mongo/cursor.rb:64:in `initialize'
/server/vendor/bundle/ruby/2.4.0/gems/mongo-2.4.1/lib/mongo/collection/view/iterable.rb:42:in `new'
/server/vendor/bundle/ruby/2.4.0/gems/mongo-2.4.1/lib/mongo/collection/view/iterable.rb:42:in `block in each'
/server/vendor/bundle/ruby/2.4.0/gems/mongo-2.4.1/lib/mongo/retryable.rb:51:in `read_with_retry'
/server/vendor/bundle/ruby/2.4.0/gems/mongo-2.4.1/lib/mongo/collection/view/iterable.rb:39:in `each'
/server/vendor/bundle/ruby/2.4.0/gems/mongoid-6.0.3/lib/mongoid/query_cache.rb:222:in `each'
/server/vendor/bundle/ruby/2.4.0/gems/mongoid-6.0.3/lib/mongoid/contextual/mongo.rb:430:in `reduce'
/server/vendor/bundle/ruby/2.4.0/gems/mongoid-6.0.3/lib/mongoid/contextual/mongo.rb:430:in `pluck'
/server/vendor/bundle/ruby/2.4.0/gems/mongoid-6.0.3/lib/mongoid/contextual.rb:20:in `pluck'
/server/vendor/bundle/ruby/2.4.0/gems/mongoid-6.0.3/lib/mongoid/findable.rb:15:in `pluck'
&lt;/code&gt;&lt;/pre&gt;</description>
      <author>lithium4010</author>
      <pubDate>Mon, 16 Jan 2017 17:01:01 +0800</pubDate>
      <link>https://ruby-china.org/topics/32144</link>
      <guid>https://ruby-china.org/topics/32144</guid>
    </item>
    <item>
      <title>升级到 2.4.0 后收到的一些 warning</title>
      <description>&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/server/vendor/bundle/ruby/2.4.0/gems/activesupport-5.0.1/lib/active_support/xml_mini.rb:51: warning: constant ::Fixnum is deprecated
/server/vendor/bundle/ruby/2.4.0/gems/activesupport-5.0.1/lib/active_support/xml_mini.rb:52: warning: constant ::Bignum is deprecated
/server/vendor/bundle/ruby/2.4.0/gems/activesupport-5.0.1/lib/active_support/core_ext/numeric/conversions.rb:138: warning: constant ::Fixnum is deprecated
/server/vendor/bundle/ruby/2.4.0/gems/elasticsearch-transport-5.0.0/lib/elasticsearch/transport/transport/base.rb:52: warning: constant ::Fixnum is deprecated
/server/vendor/bundle/ruby/2.4.0/gems/elasticsearch-transport-5.0.0/lib/elasticsearch/transport/transport/base.rb:54: warning: constant ::Fixnum is deprecated
/server/vendor/bundle/ruby/2.4.0/gems/redis-3.3.2/lib/redis/client.rb:459: warning: constant ::Fixnum is deprecated
/server/vendor/bundle/ruby/2.4.0/gems/activejob-5.0.1/lib/active_job/arguments.rb:38: warning: constant ::Fixnum is deprecated
/server/vendor/bundle/ruby/2.4.0/gems/activejob-5.0.1/lib/active_job/arguments.rb:38: warning: constant ::Bignum is deprecated
/server/vendor/bundle/ruby/2.4.0/gems/redis-3.3.2/lib/redis/client.rb:459: warning: constant ::Fixnum is deprecated
/server/vendor/bundle/ruby/2.4.0/gems/elasticsearch-transport-5.0.0/lib/elasticsearch/transport/transport/base.rb:52: warning: constant ::Fixnum is deprecated
/server/vendor/bundle/ruby/2.4.0/gems/elasticsearch-transport-5.0.0/lib/elasticsearch/transport/transport/base.rb:54: warning: constant ::Fixnum is deprecated
/server/vendor/bundle/ruby/2.4.0/gems/elasticsearch-transport-5.0.0/lib/elasticsearch/transport/transport/base.rb:52: warning: constant ::Fixnum is deprecated
/server/vendor/bundle/ruby/2.4.0/gems/elasticsearch-transport-5.0.0/lib/elasticsearch/transport/transport/base.rb:54: warning: constant ::Fixnum is deprecated
/server/vendor/bundle/ruby/2.4.0/gems/redis-3.3.2/lib/redis/client.rb:459: warning: constant ::Fixnum is deprecated
/server/vendor/bundle/ruby/2.4.0/gems/redis-3.3.2/lib/redis/client.rb:459: warning: constant ::Fixnum is deprecated
&lt;/code&gt;&lt;/pre&gt;</description>
      <author>lithium4010</author>
      <pubDate>Mon, 16 Jan 2017 16:12:52 +0800</pubDate>
      <link>https://ruby-china.org/topics/32142</link>
      <guid>https://ruby-china.org/topics/32142</guid>
    </item>
    <item>
      <title>Thin 现在好像还不能支持 Ruby 2.4.0，有什么办法吗？还是说暂时只能等一等？</title>
      <description>&lt;p&gt;已解决&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/flori/json/issues/303" rel="nofollow" target="_blank"&gt;https://github.com/flori/json/issues/303&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;直接升级的话会报错&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Gem::Ext::BuildError: ERROR: Failed to build gem native extension.

       current directory:
       /server/vendor/bundle/ruby/2.4.0/gems/json-1.8.3/ext/json/ext/generator
       /usr/local/bin/ruby -r ./siteconf20170116-11-20pdry.rb extconf.rb
       creating Makefile

       current directory:
       /server/vendor/bundle/ruby/2.4.0/gems/json-1.8.3/ext/json/ext/generator
       make "DESTDIR=" clean

       current directory:
       /server/vendor/bundle/ruby/2.4.0/gems/json-1.8.3/ext/json/ext/generator
       make "DESTDIR="
       compiling generator.c
       generator.c: In function 'generate_json':
       generator.c:861:25: error: 'rb_cFixnum' undeclared (first use in this function)
            } else if (klass == rb_cFixnum) {
                                ^
       generator.c:861:25: note: each undeclared identifier is reported only once for
       each function it appears in
       generator.c:863:25: error: 'rb_cBignum' undeclared (first use in this function)
            } else if (klass == rb_cBignum) {
                                ^
       generator.c: At top level:
       cc1: warning: unrecognized command line option "-Wno-self-assign"
       cc1: warning: unrecognized command line option "-Wno-constant-logical-operand"
       cc1: warning: unrecognized command line option "-Wno-parentheses-equality"
       cc1: warning: unrecognized command line option "-Wno-tautological-compare"
       Makefile:241: recipe for target 'generator.o' failed
       make: *** [generator.o] Error 1

       make failed, exit code 2

       Gem files will remain installed in
       /server/vendor/bundle/ruby/2.4.0/gems/json-1.8.3 for inspection.
       Results logged to
       /server/vendor/bundle/ruby/2.4.0/extensions/x86_64-linux/2.4.0/json-1.8.3/gem_make.out
&lt;/code&gt;&lt;/pre&gt;</description>
      <author>lithium4010</author>
      <pubDate>Mon, 16 Jan 2017 11:27:17 +0800</pubDate>
      <link>https://ruby-china.org/topics/32138</link>
      <guid>https://ruby-china.org/topics/32138</guid>
    </item>
    <item>
      <title>Oj.dump 一个 NaN 会出现 PI</title>
      <description>&lt;p&gt;发现一个有趣的现象&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;
&lt;span class="c1"&gt;# ruby 2.3.1p112 (2016-04-26 revision 54768) [x86_64-darwin14]&lt;/span&gt;
&lt;span class="c1"&gt;# oj (2.18.0)&lt;/span&gt;

&lt;span class="mf"&gt;2.3&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mo"&gt;006&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Oj&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dump&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="ss"&gt;a: &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;to_f&lt;/span&gt;&lt;span class="p"&gt;)})&lt;/span&gt;
&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"{&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;:a&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;:3.3e14159265358979323846}"&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;</description>
      <author>lithium4010</author>
      <pubDate>Thu, 01 Dec 2016 14:21:58 +0800</pubDate>
      <link>https://ruby-china.org/topics/31751</link>
      <guid>https://ruby-china.org/topics/31751</guid>
    </item>
  </channel>
</rss>
