<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Brad Wilson</title>
    <description>A curious individual (in more than one sense) who loves learning and thinks this whole damn world is amazing.
</description>
    <link>http://blog.lucky-dip.net/</link>
    <atom:link href="http://blog.lucky-dip.net/feed.xml" rel="self" type="application/rss+xml" />
    <pubDate>Tue, 16 May 2023 05:29:40 +0000</pubDate>
    <lastBuildDate>Tue, 16 May 2023 05:29:40 +0000</lastBuildDate>
    <generator>Jekyll v3.9.3</generator>
    
      <item>
        <title>Low Tech CI Simulation</title>
        <description>&lt;p&gt;
  Are random CI failures getting you down?
&lt;/p&gt;
&lt;p&gt;
  Are you pretty sure it's a timing issue but just can't quite reason it out?
&lt;/p&gt;
&lt;p&gt;
  Are you unable to replicate the problem locally on your mac?
&lt;/p&gt;
&lt;p&gt;
  Try my new script to slow your machine to a crawl. It'll fix you test problems guaranteed!*
&lt;/p&gt;
&lt;p class=&quot;small&quot;&gt;
  * Not a guarantee
&lt;/p&gt;
&lt;p&gt;
  &lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;c1&quot;&gt;#!/usr/bin/env ruby&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# leave one CPU free to run tests:&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;cpus&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;sb&quot;&gt;`sysctl -n hw.ncpu`&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;to_i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;

&lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Forking &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cpus&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; processes&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;..&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cpus&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;each&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Process&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;spawn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;yes &amp;gt; /dev/null&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;no&quot;&gt;Process&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;wait&lt;/span&gt;
  &lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;
  Dodgy? Yes.
&lt;/p&gt;
&lt;p&gt;
  Handy? Very.
&lt;/p&gt;
</description>
        <pubDate>Tue, 24 Feb 2015 00:00:00 +0000</pubDate>
        <link>http://blog.lucky-dip.net/articles/2015/02/24/low-tech-ci-simulation</link>
        <guid isPermaLink="true">http://blog.lucky-dip.net/articles/2015/02/24/low-tech-ci-simulation</guid>
        
        
      </item>
    
      <item>
        <title>Quieter Errors with Sidekiq</title>
        <description>&lt;p&gt;
  At my current job, we do a lot of integration with external APIs. In
  order to keep our UI snappy and our web servers happy, we send a lot of
  that communication into &lt;a href=&quot;http://sidekiq.org/&quot;&gt;Sidekiq&lt;/a&gt; workers.
&lt;/p&gt;

&lt;p&gt;
  That mostly works well, but we do hit temporary problems sometimes (network
  timeouts, random failures on the other end, etc). Sidekiq really tries hard
  to let you fix errors in workers, &lt;a href=&quot;https://github.com/mperham/sidekiq/wiki/Error-Handling&quot;&gt;trying 25 times&lt;/a&gt;
  before conceding defeat, so often these temporary failures are best handled
  by letting Sidekiq do it's thing.
&lt;/p&gt;

&lt;p&gt;
  Unfortunately when combined with an error notification service like
  &lt;a href=&quot;https://rollbar.com&quot;&gt;Rollbar&lt;/a&gt; (or &lt;a href=&quot;https://airbrake.io/&quot;&gt;Airbrake&lt;/a&gt; or
  &lt;a href=&quot;https://www.honeybadger.io/&quot;&gt;Honeybadger&lt;/a&gt;) you can end up with some
  really noisy errors. Below is a small snippet that will only send through
  the first error to Rollbar.
&lt;/p&gt;

&lt;p&gt;
  I'd prefer to be able to make every line of our app handle every possible
  error that can come up. We're working on that. Until that happens, having
  a single error per worker means we don't end up prioritising worker errors
  over web server errors becuase they look 25 times more common!
&lt;/p&gt;

&lt;p&gt;
  &lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;  &lt;span class=&quot;c1&quot;&gt;# Some Sidekiq middleware to stop us sending errors for every single&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;# retry to rollbar&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;SilenceRetryErrorMiddleware&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;call&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_worker_class&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;msg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_queue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;msg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;key?&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;retry_count&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;no&quot;&gt;Rollbar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;silenced&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;yield&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;yield&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

  &lt;span class=&quot;no&quot;&gt;Sidekiq&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;configure_server&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;config&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;config&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;server_middleware&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;chain&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;chain&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;SilenceRetryErrorMiddleware&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;/p&gt;
</description>
        <pubDate>Sat, 14 Feb 2015 00:00:00 +0000</pubDate>
        <link>http://blog.lucky-dip.net/articles/2015/02/14/quieter-errors-with-sidekiq</link>
        <guid isPermaLink="true">http://blog.lucky-dip.net/articles/2015/02/14/quieter-errors-with-sidekiq</guid>
        
        
      </item>
    
      <item>
        <title>Convert Webby to Jekyll</title>
        <description>&lt;p&gt;
  I'm going to blog more. When I think of the countless times other people sharing information
  helps me every day, I feel bad I don't share more.
&lt;/p&gt;
&lt;p&gt;
  One thing that has been acting as a block to more sharing was my old
  blog software. It was using &lt;a href=&quot;https://rubygems.org/gems/webby&quot;&gt;Webby&lt;/a&gt;.
  Webby is a nice static site generator, but one that hasn't been touched
  since 2009. Every time I wanted to post, I had to reinstall Ruby 1.8.7,
  patch together the old gems and hope everything still somehow held together.
&lt;/p&gt;
&lt;p&gt;
  That's too high a bar for me - most of the stuff I want to share isn't
  really enough to warrant that effort. It's not that I want to share total
  rubbish (I hope!), just that taking 45 minutes before I can even start a post
  really puts the pressure on.
&lt;/p&gt;
&lt;p&gt;
  So I'm finally switching to Github pages and Jekyll. With that combination
  I can write up some HTML, commit, then push. Hopefully that's convenient enough that
  I can push up scripts, hacks, random thoughts and ideas that might help others.
&lt;/p&gt;
&lt;p&gt;
  A decent way to start seems to be to post the script I used to convert
  my old posts from Webby to Jekyll. Not fancy, but it'll do the trick.

  &lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;yaml&quot;&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;root&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;[local path to old blog]&quot;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;posts&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;[local path to new blog]/_posts&quot;&lt;/span&gt;

&lt;span class=&quot;no&quot;&gt;Dir&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;glob&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;root&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;**/*.txt&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;each&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;next&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;File&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;basename&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;index.txt&quot;&lt;/span&gt;

  &lt;span class=&quot;n&quot;&gt;_junk&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;header&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;body&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;File&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;read&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;split&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;---&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

  &lt;span class=&quot;nb&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;File&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;basename&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;date&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;gsub&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;root&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;gsub&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;/&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;gsub&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;/&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;-&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;metadata&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;YAML&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;load&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;header&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;destination&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;posts&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;date&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;gsub&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'.txt'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'.html'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;

  &lt;span class=&quot;no&quot;&gt;File&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;destination&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;w&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;out&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;out&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;puts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;---&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;out&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;puts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;layout: post&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;out&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;puts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;title: &lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;metadata&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'title'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;out&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;puts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;date: &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;metadata&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'created_at'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;out&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;puts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;---&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;out&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;puts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;body&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;gsub&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\r\n&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

  &lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;destination&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;==============================&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;/p&gt;
</description>
        <pubDate>Sun, 08 Feb 2015 00:00:00 +0000</pubDate>
        <link>http://blog.lucky-dip.net/articles/2015/02/08/webby-to-jekyll</link>
        <guid isPermaLink="true">http://blog.lucky-dip.net/articles/2015/02/08/webby-to-jekyll</guid>
        
        
      </item>
    
      <item>
        <title>MongoDB  Is Mental</title>
        <description>&lt;h3&gt;Pro tip: MongoDB cursors return duplicate records&lt;/h3&gt;

&lt;p&gt;If you are iterating through a data set, you should switch from:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Object.each { |o| ... }
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;to&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Object.extras(hint: { _id: 1 }).each { |o| ... }
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;That example uses Mongoid, but this is a MongoDB problem, not a Mongoid one. It&amp;rsquo;s likely it affects other MongoDB libraries.&lt;/p&gt;

&lt;h3&gt;Students get too many awards&lt;/h3&gt;

&lt;p&gt;Each week, our systems distribute awards to students if they achieve certain goals. We started doing this naively: iterating through each record and calling a method on the object.
This has a few benefits:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;the code is really easy to follow&lt;/li&gt;
&lt;li&gt;for now, it runs quickly enough for our needs&lt;/li&gt;
&lt;li&gt;it works&lt;/li&gt;
&lt;/ol&gt;


&lt;p&gt;At least, we thought it worked. We&amp;rsquo;d started to notice more and more reports of people getting two awards where they should only be getting one. The awards were effectively identical, with only slight differences in created_at times to tell them apart.&lt;/p&gt;

&lt;p&gt;We ruled out some of the obvious potential causes: our crons were only firing once, the code wasn&amp;rsquo;t accidentally creating two awards.&lt;/p&gt;

&lt;p&gt;The only other possible solution we could see is if our iteration was somehow returning the same object twice. Nah, that can&amp;rsquo;t be it&amp;hellip; that&amp;rsquo;d be insane&amp;hellip; that&amp;rsquo;d be impossible&amp;hellip;&lt;/p&gt;

&lt;blockquote&gt;&lt;p&gt;Once you eliminate the impossible, whatever remains, no matter how improbable, must be the truth.&lt;/p&gt;

&lt;p&gt;&lt;cite&gt;Arthur Conan Doyle&lt;/cite&gt;&lt;/p&gt;&lt;/blockquote&gt;

&lt;h3&gt;The Internet to the rescue!&lt;/h3&gt;

&lt;p&gt;We stumbled across &lt;a href=&quot;http://stackoverflow.com/questions/16936299/rails-and-mongoid-returning-duplicate-records-for-query&quot;&gt;this post on stack overflow&lt;/a&gt; which suggested &lt;em&gt;that was it&lt;/em&gt;. By default, &lt;a href=&quot;http://docs.mongoDBdb.org/manual/reference/operator/snapshot/&quot;&gt;mongoDB returns documents more than once if a write operation moves the data&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;A few test iterations through &amp;ldquo;all&amp;rdquo; records in our db confirmed that iterating &lt;em&gt;without&lt;/em&gt; a hint resulted in duplicates. Adding the hint meant we only got each record once. As far as we can tell, this is a MongoDB problem, not a Mongoid problem.&lt;/p&gt;

&lt;h3&gt;Rant&lt;/h3&gt;

&lt;p&gt;It&amp;rsquo;s not impossible that there is somebody out there has a need to return records twice in one iteration. Maybe. Regardless, there&amp;rsquo;s no way that is most common use case. MongoDB really doesn&amp;rsquo;t have that &lt;a href=&quot;http://blogs.msdn.com/b/brada/archive/2003/10/02/50420.aspx&quot;&gt;pit of success&lt;/a&gt; stuff down. This just seems like another time when MongoDB defaults are either wrong, misleading, or useless.&lt;/p&gt;

&lt;p&gt;:sigh:&lt;/p&gt;

&lt;p&gt;(Thanks to &lt;a href=&quot;http://stackoverflow.com/users/596956/jimoleary&quot;&gt;jimoleary&lt;/a&gt; for the helpful Stack Overflow comment)&lt;/p&gt;

&lt;p&gt;(Originally posted at &lt;a href=&quot;http://dev.blake.com.au/blog/2013/09/25/mongo-is-mental/&quot;&gt;on the Blake Dev Team Blog&lt;/a&gt;)&lt;/p&gt;
</description>
        <pubDate>Sat, 28 Sep 2013 02:02:29 +0000</pubDate>
        <link>http://blog.lucky-dip.net/articles/2013/09/28/mongo-is-mental</link>
        <guid isPermaLink="true">http://blog.lucky-dip.net/articles/2013/09/28/mongo-is-mental</guid>
        
        
      </item>
    
      <item>
        <title>Dynamic Sites on Nginx With Passenger</title>
        <description>&lt;p&gt;
  If you are using passenger with nginx, it's possible to set nginx up in a way that
  allows new apps (or branches of the same app) to be deployed with no change to the
  server config.
&lt;/p&gt;
&lt;p&gt;
  &lt;h3&gt;Step 1&lt;/h3&gt;
  Add this config to your nginx.conf. Edit the hostname to match your server, and
  the root to match your deploy directory
  &lt;pre&gt;server {
   server_name ~^([-\w]+)\.yourdomain.com;
   root /var/www/$1/current/public;
   passenger_enabled on;
}&lt;/pre&gt;
&lt;/p&gt;
&lt;p&gt;
  &lt;h3&gt;Step 2&lt;/h3&gt;
  Deploy your rails app to /var/www/whatever/current. The app will then be available
  at http://whatever.yourdomain.com.
  &lt;br/&gt;&lt;br/&gt;
  Similarly, deploying to /var/www/some-internal-app/current means the app will be available at
  http://some-internal-app.yourdomain.com
&lt;/p&gt;
&lt;p&gt;
  &lt;h3&gt;Notes&lt;/h3&gt;
  This technique probably isn't ideal for production sites, but for internal and or
  temporary sites it is quite useful. Passenger takes care of spinning up apps as they
  are requested, so if one app is getting lots of requests, passenger will naturally
  spin up more app servers for that one, potentially spinning down unused apps. Providing
  all apps aren't being constantly accessed, this acts as a kind of resource balancing
  allowing an underpowered internal server to serve a lot of apps.
&lt;/p&gt;
</description>
        <pubDate>Sat, 04 May 2013 04:26:22 +0000</pubDate>
        <link>http://blog.lucky-dip.net/articles/2013/05/04/dynamic-sites-on-nginx-with-passenger</link>
        <guid isPermaLink="true">http://blog.lucky-dip.net/articles/2013/05/04/dynamic-sites-on-nginx-with-passenger</guid>
        
        
      </item>
    
      <item>
        <title>Webby on Heroku</title>
        <description>&lt;h3&gt;The $20 a month more for beer dream&lt;/h3&gt;
&lt;p&gt;
  I've been hosting this blog on Slicehost for a while now. They have been a
  good host, but a full slice is more than I need these days.
&lt;/p&gt;

&lt;h3&gt;The plan&lt;/h3&gt;
&lt;p&gt;
  After a bit of thinking, I realised I could pretty easily move this blog
  across to Heroku. It's just a bunch of static files created by 
  &lt;a href=&quot;http://webby.rubyforge.org/&quot;&gt;Webby&lt;/a&gt;, so I figured a tiny
  &lt;a href=&quot;http://www.sinatrarb.com/&quot;&gt;Sinatra&lt;/a&gt; app would be just the trick.
&lt;/p&gt;

&lt;h3&gt;The problem&lt;/h3&gt;
&lt;p&gt;
  Sinatra is perfect for these kind of tiny jobs, and ended up working without
  too much effort. I had a bit of a wrestle with Heroku initially. 
  I couldn't seem to get heroku to read my articles. They were stored in a
  directory called &quot;output&quot;. 
&lt;/p&gt;

&lt;h3&gt;The solution&lt;/h3&gt;
&lt;p&gt;
  After a while, I tried tried renaming the directory to &quot;public&quot;. That 
  seemed to do the trick. Heroku mentions that you can &lt;i&gt;read&lt;/i&gt; the filesystem
  but I couldn't find too much mention of exactly &lt;i&gt;what&lt;/i&gt; you can read.
  A directory called &quot;public&quot; seems like a pretty safe bet to be readable forever 
  though.
  I told Webby to start buiding to the public directory instead. Here's my 
  SiteFile:
  &lt;pre&gt;SITE.blog_dir = &quot;articles&quot;
SITE.output_dir = &quot;public&quot;&lt;/pre&gt;
&lt;/p&gt;
  
&lt;h3&gt;The app&lt;/h3&gt;
&lt;p&gt;
  After getting that working, the script worked on Heroku. It's just as 
  simple as I'd hoped it would be. 
  &lt;pre class=&quot;brush: ruby&quot;&gt;require &quot;rubygems&quot;
require &quot;sinatra&quot;

DIR = 'public'
set :public, DIR

get '/' do
  read('index.html')
end

get '/articles/*' do
  read('articles', params[&quot;splat&quot;], 'index.html')
end

def read(*parts)
  File.read(File.join([ DIR ] + parts))
end&lt;/pre&gt;
&lt;/p&gt;
&lt;p&gt;
  Not much to it - read index.html for the root path, or read the article 
  page for any article. It'd probably be possible to merge these into a single
  route, but it seems like that would just complicate things unecessarily. 
&lt;/p&gt;
&lt;h3&gt;The source&lt;/h3&gt;
&lt;p&gt;
  &lt;a href=&quot;http://github.com/bradx3/blog&quot;&gt;http://github.com/bradx3/blog&lt;/a&gt;
&lt;/p&gt;
</description>
        <pubDate>Fri, 11 Jun 2010 07:48:47 +0000</pubDate>
        <link>http://blog.lucky-dip.net/articles/2010/06/11/webby-on-heroku</link>
        <guid isPermaLink="true">http://blog.lucky-dip.net/articles/2010/06/11/webby-on-heroku</guid>
        
        
      </item>
    
      <item>
        <title>Fundation</title>
        <description>&lt;p&gt;
  I've kept my saving in a single, high interest account for a while now. It
  works particularly well as a contractor in that I can put aside tax and GST
  and earn interest on that before I have to pay it to the government.
&lt;/p&gt;
&lt;p&gt;
  It has been a bit difficult to keep track of how much money was saving, and how
  much was tax/GST though, so I've written a simple app to keep track.
&lt;/p&gt;
&lt;p&gt;
  &lt;a href=&quot;http://fundation.lucky-dip.net&quot;&gt;Fundation&lt;/a&gt; lets you set up
  funds to manage your saving. Each paycheck can be automatically divided up
  into the different funds in ratios you specify.
&lt;/p&gt;
&lt;p&gt;
  Anyway, &lt;a href=&quot;http://fundation.lucky-dip.net&quot;&gt;Fundation&lt;/a&gt; is free to use,
  so if you're having trouble remembering how much money you've got to spend, give it
  a try &lt;a href=&quot;http://fundation.lucky-dip.net&quot;&gt;here&lt;/a&gt;.
&lt;/p&gt;
&lt;p&gt;
  If you have any errors in Fundation, or any suggestions for improvements,
  please use the comments of this post to provide them.
&lt;/p&gt;
</description>
        <pubDate>Mon, 07 Sep 2009 03:40:10 +0000</pubDate>
        <link>http://blog.lucky-dip.net/articles/2009/09/07/fundation</link>
        <guid isPermaLink="true">http://blog.lucky-dip.net/articles/2009/09/07/fundation</guid>
        
        
      </item>
    
      <item>
        <title>Restart Passenger From Emacs Using Rinari</title>
        <description>&lt;p&gt;
Being able to completely re-program your editor is fun. I feel like I've got a 
long way to go before I'm an Emacs Guru (if anybody *ever* becomes a true
Emacs Guru), but it's nice being able to easily
automate things I do in my editor.
&lt;/p&gt;
&lt;p&gt;
I've been experimenting with using &lt;a href=&quot;http://www.modrails.com/&quot;&gt;Passenger&lt;/a&gt;
in development instead of script/server. It's not too bad. It's nice to have
a server always ready to go, but it does make dropping down to the debugger
difficult.
&lt;/p&gt;
&lt;p&gt;
Anyway, here is a small snippet of emacs lisp to easily restart the Passenger
server for the project you are currently working on. It assumes you have 
&lt;a href=&quot;http://rinari.rubyforge.org/&quot;&gt;Rinari&lt;/a&gt; installed.

&lt;h4&gt;The function:&lt;/h4&gt;
&lt;pre class=&quot;brush: plain&quot;&gt;
(defun restart-passenger ()
  &quot;Restart passenger using the current rinari root&quot; (interactive)
  (shell-command (concat &quot;touch &quot; (rinari-root) &quot;tmp/restart.txt&quot;)))
&lt;/pre&gt;
&lt;h4&gt;And to bind it to a key&lt;/h4&gt;
&lt;pre class=&quot;brush: plain&quot;&gt;
(global-set-key (kbd &quot;C-c ' p&quot;) 'restart-passenger)
&lt;/pre&gt;
&lt;/p&gt;
</description>
        <pubDate>Thu, 06 Aug 2009 04:27:33 +0000</pubDate>
        <link>http://blog.lucky-dip.net/articles/2009/08/06/restart-passenger-from-emacs-using-rinari</link>
        <guid isPermaLink="true">http://blog.lucky-dip.net/articles/2009/08/06/restart-passenger-from-emacs-using-rinari</guid>
        
        
      </item>
    
      <item>
        <title>My Backup Script</title>
        <description>&lt;p&gt;
  This is my simple backup script. It keeps everything I don't already have backed up 
  in version control safe and sound from hardware failure. Not from me though - 
  if I delete a file accidentally, that file is really gone
  (unless you act fast before the next backup runs!). 
  If I make a bad edit, that file is busted.
  &lt;br /&gt;
  &lt;br /&gt;
  But I can live with that. 
&lt;/p&gt;

&lt;p&gt;
  &lt;h3&gt;backup.rb&lt;/h3&gt;
  Backup.rb uses rsync over ssh to backup a number of different server. Rsync is good
  because it only sends what changed, so we're not transferring gigs every night.
  &lt;br /&gt;&lt;br /&gt;
  You'll have to make some changes to the SSH_USER, REMOTE_DIR and HOSTS constants. 
  You could also add any file types you want to ignore to the EXCLUDES list.

  &lt;pre class=&quot;brush: ruby&quot;&gt;
#!/usr/bin/env ruby

NAME = %x{ hostname }.strip
SSH_USER = &quot;brad&quot;
REMOTE_DIR = &quot;/home/brad/Backups/#{ NAME }&quot;

HOSTS = [ &quot;clamps&quot;, &quot;hubert.lucky-dip.net&quot; ]
DIRS = [
        &quot;~/Library&quot;, 
        &quot;~/Documents&quot;,
        &quot;~/Pictures&quot;
]
EXCLUDES = [
            &quot;*Cache*&quot;,
            &quot;*NewsFire*&quot;,
            &quot;*Cookies*&quot;,
            &quot;*.log&quot;,
            &quot;HistoryIndex.ox*&quot;,
            &quot;*Virtual Machines*&quot;,
            &quot;*.resume&quot;,
            &quot;*.ipsw&quot;,
            &quot;*.dmg&quot;,
            &quot;*.corrupt&quot;
]

HOSTS.each do |host|
  DIRS.each do |dir|
    puts &quot;
</description>
        <pubDate>Thu, 23 Jul 2009 22:25:51 +0000</pubDate>
        <link>http://blog.lucky-dip.net/articles/2009/07/23/my-backup-script</link>
        <guid isPermaLink="true">http://blog.lucky-dip.net/articles/2009/07/23/my-backup-script</guid>
        
        
      </item>
    
      <item>
        <title>Creating a jruby rails project</title>
        <description>&lt;p&gt;
For some reason, this command:
&lt;pre class=&quot;brush: bash&quot;&gt;
jruby -S gem install mongrel activerecord-jdbcmysql-adapter rails
&lt;/pre&gt;
didn't install all the required gems I needed.
&lt;/p&gt;
&lt;p&gt;
Manually listing all the basic rails gems needed fixed the problem for me though. Working command:
&lt;pre class=&quot;brush: bash&quot;&gt;
jruby -S gem install mongrel activerecord-jdbcmysql-adapter rails \
activesupport actionmailer activerecord actionpack activeresource
&lt;/pre&gt;
</description>
        <pubDate>Thu, 09 Jul 2009 22:08:26 +0000</pubDate>
        <link>http://blog.lucky-dip.net/articles/2009/07/09/creating-a-jruby-rails-project</link>
        <guid isPermaLink="true">http://blog.lucky-dip.net/articles/2009/07/09/creating-a-jruby-rails-project</guid>
        
        
      </item>
    
  </channel>
</rss>
