<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>Repeating Beats</title>
  <subtitle>Relentless Forward Motion</subtitle>
  <id>http://www.repeatingbeats.com/</id>
  <link href="http://www.repeatingbeats.com/"/>
  <link href="http://www.repeatingbeats.com/feed.xml" rel="self"/>
  <updated>2013-02-18T00:00:00Z</updated>
  <author>
    <name>Steve Lloyd</name>
  </author>
  <entry>
    <title>A State of Refactoring</title>
    <link rel="alternate" href="/writings/2013/02/18/a-state-of-refactoring/"/>
    <id>/writings/2013/02/18/a-state-of-refactoring/</id>
    <published>2013-02-18T00:00:00Z</published>
    <updated>2013-02-18T00:00:00Z</updated>
    <author>
      <name>Steve Lloyd</name>
    </author>
    <summary type="html">&lt;p&gt;I was recently working on a feature with requirements and constraints that can be boiled down to:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Listen for filesystem change events and initiate an asynchronous worker process. The simplified watcher API:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;:::javascript
 var watcher = require(&amp;#39;./watcher&amp;#39;);&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;/ol&gt;</summary>
    <content type="html">&lt;p&gt;I was recently working on a feature with requirements and constraints that can be boiled down to:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Listen for filesystem change events and initiate an asynchronous worker process. The simplified watcher API:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;:::javascript
 var watcher = require(&amp;#39;./watcher&amp;#39;);

 watcher.on(&amp;#39;change&amp;#39;, function () {
   // Do something useful
 });&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;

&lt;li&gt;
&lt;p&gt;The worker process cannot handle concurrency, so ensure only one worker is running at a time. The simplified worker API:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;:::javascript
 var worker = require(&amp;#39;./worker&amp;#39;);

 worker.run(function (err) {
   // Invoked when the worker is done
 });&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;

&lt;li&gt;
&lt;p&gt;If a change event is emitted while the process is running, mark the output as stale and re-run the process when it finishes.&lt;/p&gt;
&lt;/li&gt;

&lt;li&gt;
&lt;p&gt;While stale, any additional change events can be ignored, and the process only needs to be re-run once.&lt;/p&gt;
&lt;/li&gt;

&lt;li&gt;
&lt;p&gt;In JavaScript.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id='branching_out'&gt;Branching Out&lt;/h2&gt;

&lt;p&gt;As I was exploring the problem space, my first cut at a solution that passed my tests looked a lot like:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;:::javascript
var worker = require(&amp;#39;./worker&amp;#39;)
  , watcher = require(&amp;#39;./watcher&amp;#39;)
  , working = false
  , stale = false;

watcher.on(&amp;#39;change&amp;#39;, function () {

  function handler(err) {
    if (err) {
      console.error(err.stack);
      return process.exit(1);
    }

    if (stale) {
      stale = false;
      worker.run(handler);
    }
    else {
      working = false;
    }
  }

  if (!working) {
    working = true;
    worker.run(handler);
  }
  else { // working
    stale = true;
  }

});&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This solution uses two variables at module scope (&lt;code&gt;working&lt;/code&gt; and &lt;code&gt;stale&lt;/code&gt;) to keep track of system state. Change events and worker callbacks branch on the current state to determine the necessary state modifications and worker strategy. The worker callback needs to reference itself to handle the stale case.&lt;/p&gt;

&lt;p&gt;This code &lt;em&gt;works&lt;/em&gt;, but it&amp;#8217;s not very easy to read. There is a lot of bookkeeping around the two state variables. A reader would be very hardpressed to infer the problem requirements from the code itself. In other words, it&amp;#8217;s the kind of code that is just asking for bugs the next time an unfamiliar developer dives into it.&lt;/p&gt;

&lt;h2 id='state_meet_machine'&gt;State, Meet Machine&lt;/h2&gt;

&lt;p&gt;While attempting to refactor my initial implementation into something cleaner and more maintainable, I noted that I was effectively building a machine with three states (&lt;code&gt;ready&lt;/code&gt;, &lt;code&gt;working&lt;/code&gt;, &lt;code&gt;stale&lt;/code&gt;) that responds to two events (&lt;code&gt;change&lt;/code&gt;, &lt;code&gt;done&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;&lt;img alt='Simple State Machine' src='/images/statem.png' /&gt;&lt;/p&gt;

&lt;p&gt;The machine&amp;#8217;s transitions can be described with a simple JavaScript object:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;:::javascript
{
  ready: {
    change: &amp;#39;working&amp;#39;
  }
, working: {
    change: &amp;#39;stale&amp;#39;
  , done: &amp;#39;ready&amp;#39;
  }
, stale: {
    change: &amp;#39;stale&amp;#39;
  , done: &amp;#39;working&amp;#39;
  }
}&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Given this declarative state machine definition, all I needed was a way to proxy watcher change events to the machine and observe when the machine entered the working state. This yields a considerably more straightforward solution:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;:::javascript
var statem = require(&amp;#39;statem&amp;#39;)
  , worker = require(&amp;#39;./worker&amp;#39;)
  , watcher = require(&amp;#39;./watcher&amp;#39;)
  , machine;

machine = statem.machine({
  initial: &amp;#39;ready&amp;#39;
, states: {
    ready: {
      change: &amp;#39;working&amp;#39;
    }
  , working: {
      change: &amp;#39;stale&amp;#39;
    , done: &amp;#39;ready&amp;#39;
    }
  , stale: {
      change: &amp;#39;stale&amp;#39;
    , done: &amp;#39;working&amp;#39;
    }
  }
});

machine.onEnter(&amp;#39;working&amp;#39;, function () {
  worker.run(function (err) {
    if (err) {
      console.error(err.stack);
      return process.exit(1);
    }
  
    machine.send(&amp;#39;done&amp;#39;);
  });
});

watcher.on(&amp;#39;change&amp;#39;, function () {
  machine.send(&amp;#39;change&amp;#39;);
});&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id='one_little_problem'&gt;One Little Problem&lt;/h2&gt;

&lt;pre&gt;&lt;code&gt;➜ ~ npm info statem
npm http GET https://registry.npmjs.org/statem
npm http 404 https://registry.npmjs.org/statem
npm ERR! 404 &amp;#39;statem&amp;#39; is not in the npm registry.
npm ERR! 404 You should bug the author to publish it&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;I often write code to APIs that don&amp;#8217;t exist, if only to fully understand what the perfect API looks like from the consumer perspective. There is a limit to this, but I definitely don&amp;#8217;t like pushing complexity to the consumer when it can be avoided.&lt;/p&gt;

&lt;p&gt;In this case, I found myself staring at &lt;a href='http://nodetoolbox.com/search?q=state+machine'&gt;a wall of JavaScript state machines&lt;/a&gt;, none of which really provided the semantics and simplicity I was looking for. Pragmatism won the day, and I ended up shipping the feature with &lt;a href='https://github.com/jakesgordon/javascript-state-machine'&gt;javascript-state-machine&lt;/a&gt;, but I eventually found time to poke at the problem a bit myself.&lt;/p&gt;

&lt;p&gt;I now have a mostly complete &lt;a href='https://github.com/repeatingbeats/statem'&gt;implementation of statem&lt;/a&gt; built on top of Node&amp;#8217;s EventEmitter. I haven&amp;#8217;t published it yet, mostly because I need to explore how I want the libary to behave in error cases (invalid states, invalid transitions, etc.). I&amp;#8217;m also a bit wary of adding to the proliferation of state machine options without a compelling differentiator. Though it seems doing so &lt;em&gt;is&lt;/em&gt; The Node Way™.&lt;/p&gt;

&lt;p&gt;In the meantime, consider it a work in progress.&lt;/p&gt;</content>
  </entry>
  <entry>
    <title>Ship It</title>
    <link rel="alternate" href="/writings/2013/02/05/ship-it/"/>
    <id>/writings/2013/02/05/ship-it/</id>
    <published>2013-02-05T00:00:00Z</published>
    <updated>2013-02-05T00:00:00Z</updated>
    <author>
      <name>Steve Lloyd</name>
    </author>
    <summary type="html">&lt;p&gt;It has been slightly over two years since I have written in this space. My &amp;#8221;I&amp;#8217;m going to have a blog&amp;#8221; movement of early 2011 did not last very long. I&amp;#8217;m a very busy man.&lt;/p&gt;

&lt;p&gt;I started getting the itch to write again late last year. By that point, I was both displeased by my previous design attempts and subtly discouraged by the richness of the Wordpress authoring experience. I wanted to whip up some Markdown, publish, and call it a day. And the rewrite began.&lt;/p&gt;</summary>
    <content type="html">&lt;p&gt;It has been slightly over two years since I have written in this space. My &amp;#8221;I&amp;#8217;m going to have a blog&amp;#8221; movement of early 2011 did not last very long. I&amp;#8217;m a very busy man.&lt;/p&gt;

&lt;p&gt;I started getting the itch to write again late last year. By that point, I was both displeased by my previous design attempts and subtly discouraged by the richness of the Wordpress authoring experience. I wanted to whip up some Markdown, publish, and call it a day. And the rewrite began.&lt;/p&gt;

&lt;p&gt;Goodbye Wordpress, PHP, MySQL, CSS, and WYSIWYG.&lt;/p&gt;

&lt;p&gt;Hello Middleman, Ruby, S3, SASS, and Markdown.&lt;/p&gt;

&lt;p&gt;It&amp;#8217;s all to easy for me to fall into the trap where I don&amp;#8217;t ship because I&amp;#8217;m tweaking and polishing to perfection. Or at least to the closest approximation to perfection that I might stand a chance at achieving. The irony is not lost on me that I have spent far more hours hacking on the implementation of this site than I have actually writing content for it.&lt;/p&gt;

&lt;p&gt;Current status? It&amp;#8217;s far from perfect. Some of the code is downright sloppy. My stylesheets and layouts are disorganized. The list of user-facing TODOs is far from complete.&lt;/p&gt;

&lt;p&gt;So I&amp;#8217;m shipping it.&lt;/p&gt;</content>
  </entry>
  <entry>
    <title>One Thread to Rule Them All</title>
    <link rel="alternate" href="/writings/2011/03/08/one-thread-to-rule-them-all/"/>
    <id>/writings/2011/03/08/one-thread-to-rule-them-all/</id>
    <published>2011-03-08T00:00:00Z</published>
    <updated>2011-03-08T00:00:00Z</updated>
    <author>
      <name>Steve Lloyd</name>
    </author>
    <summary type="html">&lt;p&gt;Among other assertions, the &lt;a href='http://nodejs.org/'&gt;Node.js&lt;/a&gt; home page declares, “Because nothing blocks, less-than-expert programmers are able to develop fast systems.” It’s tempting to jump to the conclusion that Node.js is a panacea for the difficulties of developing complex systems. Counterpoint: &lt;a href='http://groups.google.com/group/nodejs/browse_thread/thread/c334947643c80968/8d9ab9481199c5d8'&gt;I love async, but I can’t code like this&lt;/a&gt;. Perhaps there is a degree of nuance to the aysynchronous programming model.&lt;/p&gt;</summary>
    <content type="html">&lt;p&gt;Among other assertions, the &lt;a href='http://nodejs.org/'&gt;Node.js&lt;/a&gt; home page declares, “Because nothing blocks, less-than-expert programmers are able to develop fast systems.” It’s tempting to jump to the conclusion that Node.js is a panacea for the difficulties of developing complex systems. Counterpoint: &lt;a href='http://groups.google.com/group/nodejs/browse_thread/thread/c334947643c80968/8d9ab9481199c5d8'&gt;I love async, but I can’t code like this&lt;/a&gt;. Perhaps there is a degree of nuance to the aysynchronous programming model.&lt;/p&gt;

&lt;p&gt;The techniques described in the remainder of this post were not invented by me. There are numerous libraries dedicated to unwinding asynchronous spaghetti callback hell, one of which (&lt;a href='https://github.com/caolan/async'&gt;async.js&lt;/a&gt;) does things very similar to what I’m going to describe. But that’s not the point. The objective here is to identify some common async coding patterns, exercise the javascripty side of my brain to drum up solutions, and hopefully illuminate a point or two in the process.&lt;/p&gt;

&lt;p&gt;The code presented in this post can be examined in its fully glory over at &lt;a href='https://gist.github.com/859935'&gt;Github&lt;/a&gt;. This script can be invoked with node on the command line.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ node asynchronicity.js&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;One final caveat. This post is quite long, and I decided not to make it quite longer by dealing with errors. All of my examples, in reality, need to handle errors. I’ll save that as an exercise for the reader.&lt;/p&gt;

&lt;h2 id='our_first_contrived_example'&gt;Our First Contrived Example&lt;/h2&gt;

&lt;p&gt;Imagine we want to retrieve some data over a very slow network, and we only have one thread on which to do it. Let’s look at the uber-simple synchronous model:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;:::javascript
// Slow network getters
var get_first_part = function() {
    // Pretend this blocks for three seconds.
      return &amp;#39;hello&amp;#39;;
};
var get_second_part = function() {
    // Pretend this blocks for one second.
      return &amp;#39;world&amp;#39;;
};
// Let&amp;#39;s get some data!
console.log(get_first_part() + &amp;#39; &amp;#39; + get_second_part());&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Simple. Easy. Wonderful. Other than the fact that our lone thread is locked up for four seconds while we sit around waiting to print ‘hello world’.&lt;/p&gt;

&lt;h2 id='asynchronize_it'&gt;Asynchronize It&lt;/h2&gt;

&lt;p&gt;Instead of waiting around doing nothing while we wait for the slow network to respond, we can pass callback functions that will be invoked when the data is available. Now we have getters that look something like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;:::javascript
var slow_network = {

  get_first_part: function (callback) {
    setTimeout(function() { callback(&amp;#39;hello&amp;#39;); }, 3000);
  },

  get_second_part: function (callback) {
    setTimeout(function() { callback(&amp;#39;async&amp;#39;); }, 1000);
  },

  get_third_part: function (callback) {
    setTimeout(function() { callback(&amp;#39;world&amp;#39;); }, 500);
  },

};&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;At this point, I’ll also introduce a quick helper that will be used to report results and timing information for async operations.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;:::javascript
var exhibit = function (title) {
  var start_time = Date.now();

  return {
    log: function (msg) {
      console.log(title + &amp;#39;: &amp;#39; + msg);
    },
    report: function (result) {
      console.log(&amp;#39;report for &amp;#39; + title +
                  &amp;#39;:\n\tresult: &amp;#39; + result +
                  &amp;#39;\n\telapsed: &amp;#39; +
                  (Date.now() - start_time) + &amp;#39; ms&amp;#39;);
    }
  };
};&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;It is common to use nested callbacks to for asynchronous functions. Let’s retrive our data over the slow async network:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;:::javascript
var exhibit_a = exhibit(&amp;#39;basic nested callbacks&amp;#39;);

slow_network.get_first_part(function (first_part) {
  slow_network.get_second_part(function (second_part) {
    slow_network.get_third_part(function (third_part) {
      exhibit_a.report([first_part, second_part, third_part].join(&amp;#39; &amp;#39;));
    });
  });
});&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This doesn’t look all that scary, but it’s trending considerably toward spaghetti when compared to our original synchronous version. When each callback requires additional logic before carrying on to the next invocation, it can be very difficult to retain a clear mental context for what is happening.&lt;/p&gt;

&lt;p&gt;More importantly, there’s absolutely no reason to invoke these independent functions sequentially. It took four and a half seconds to get to ‘hello async world’ despite the fact that no individual call took longer than three seconds. We should be able fire off all three methods at once and carry on as soon as all three have responded. First, the ugly way:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;:::javascript
var exhibit_b = exhibit(&amp;#39;parallel polling&amp;#39;);
var first, second, third;

slow_network.get_first_part(function (first_part) {
  first = first_part;
});

slow_network.get_second_part(function (second_part) {
  second = second_part;
});

slow_network.get_third_part(function (third_part) {
  third = third_part;
});

var interval_id = setInterval(function () {
  if (first &amp;amp;&amp;amp; second &amp;amp;&amp;amp; third) {
    clearInterval(interval_id);
    exhibit_b.report([first, second, third].join(&amp;#39; &amp;#39;));
  }
}, 100);&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id='yes_that_polling_timer_is_gross'&gt;Yes, That Polling Timer is Gross&lt;/h2&gt;

&lt;p&gt;Speaking more generally, we have a number of asynchronous functions executing in parallel, and we have code that cannot be executed until all of the parallel functions have called back. This is a common pattern in async programming, so we certainly need a better solution than polling. The following helper method allows us to specify our async functions as a series of arguments. The final argument is the callback that will be invoked once all of the parallel functions have called back. This callback provides an array of arbitray result objects that correspond to each of the parallel functions.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;:::javascript
var async_helper = {

  parallel: function () {

    var args = Array.prototype.slice.call(arguments),
        callback = args.pop(),
        results = [],
        in_progress = args.length;

    args.forEach(function (async_call, index) {
      async_call(function (result) {
        results[index] = result;
        if (--in_progress == 0) {
          callback(results);
        }
      });
    });
  }

};&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Aided by the parallel helper, our slow network example now looks like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;:::javascript
var exhibit_c = exhibit(&amp;#39;async.parallel&amp;#39;);

async_helper.parallel(
  slow_network.get_first_part,
  slow_network.get_second_part,
  slow_network.get_third_part,
  function (results) {
    exhibit_c.report(results.join(&amp;#39; &amp;#39;));
  }
);&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This form is more efficient than simple nested callbacks, and in my opinion also more readable.&lt;/p&gt;

&lt;h2 id='avoiding_sequential_callback_hell'&gt;Avoiding Sequential Callback Hell&lt;/h2&gt;

&lt;p&gt;We don’t always have the luxury of calling functions in parallel. If each function in a sequence needs to pass its results to the next function, we can’t improve in efficiency over the nested async callbacks. We can, however, still provide a helper to keep sequential async calls clean and readable:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;:::javascript
var async_helper = {

  parallel: function () {

  // See implementation above ...

  },

  sequence: function () {

    var args = Array.prototype.slice.call(arguments),
        callback = args.pop(),
        results = [];

    function next() {
      var func = args.shift();

      func(function (result) {
        results.push(result);
        args.length &amp;gt; 0 ? next() : callback(results);
      }, results);
    }

    next();
  }

};&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Note that the sequential function calls take two arguments: a function callback and a results object. This allows the results to be passed down the sequence. If we pretend that ‘hello async world’ can’t be retrieved in parallel, the sequential helper could be used like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;:::javascript
var exhibit_d = exhibit(&amp;#39;async_helper.sequence&amp;#39;);

async_helper.sequence(
  slow_network.get_first_part,
  slow_network.get_second_part,
  slow_network.get_third_part,
  function (results) {
    exhibit_d.report(results.join(&amp;#39; &amp;#39;));
  }
);&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id='mix_it_up'&gt;Mix It Up&lt;/h2&gt;

&lt;p&gt;The sequence and parallel helpers can, of course, be combined to create more complex sets of async function calls. For my next contrived example, assume that we have a disk that is extremely slow to read. Fortunately, our contrived slow disk allows us to do some reads in parallel. (Yes, I’m completely making something up to suit the problem I want to solve).&lt;/p&gt;

&lt;p&gt;Our contrived disk has two kinds of reads. Direct reads are invoked with a getter and call back with a numeric value. Indirect reads are also invoked with a getter, but indirect reads call back with the name of a direct getter that then must be called to retrieve a value.&lt;/p&gt;

&lt;p&gt;Pretend that our awesome slow disk has the following getters:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;#39;get_a&amp;#39; -&amp;gt; &amp;#39;get_e&amp;#39; (indirect)
&amp;#39;get_b&amp;#39; -&amp;gt; &amp;#39;get_c&amp;#39; (indirect)
&amp;#39;get_c&amp;#39; -&amp;gt;    2    (direct)
&amp;#39;get_d&amp;#39; -&amp;gt;    5    (direct)
&amp;#39;get_e&amp;#39; -&amp;gt;    1    (direct)&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;First, I’ll build an object that implements my slow disk’s behavior.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;:::javascript
var slow_disk = (function () {

  var getter_factory = function(getters) {

    var widget = {},
        params = null,
        name = null;

    function build_getter(val, delay) {
      return function (callback, results) {
        setTimeout(function() { callback(val); }, delay);
      };
    }

    for (name in getters) {
      params = getters[name];
      widget[name] = build_getter(params.val, params.delay);
    }

    return widget;
  }

  return getter_factory({
    get_a: { val: &amp;#39;get_e&amp;#39;, delay: 2000 },
    get_b: { val: &amp;#39;get_c&amp;#39;, delay: 3000 },
    get_c: { val: 2, delay: 1000 },
    get_d: { val: 5, delay: 1500 },
    get_e: { val: 1, delay: 5000 },
  });

}());&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now that we have a contrived slow disk, let’s invent a problem to solve with async helpers. I want to know the answer to:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;a + b + c + d + e&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;We need to get five values in parallel, and for the indirect values we need to make two sequential calls. We’ll hold off on cleverness for the moment and implement that directly:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;:::javascript
var exhibit_e = exhibit(&amp;#39;parallel/sequence mix&amp;#39;);

async_helper.parallel(

  // Get a, then get the value of what a points to
  function (callback) {
    async_helper.sequence(
      slow_disk.get_a,
      function (callback, results) {
        slow_disk[results[0]](function (val) { callback(val); });
      },
      function (results) {
        // We want the result of the second function
        callback(results[1]);
      }
    );
  },

  // Get b, then get the value of what b points to
  function (callback) {
    async_helper.sequence(
      slow_disk.get_b,
      function (callback, results) {
        slow_disk[results[0]](function (val) { callback(val); });
      },
      function (results) {
        // Again, we want the result of the second function
        callback(results[1]);
      }
    );
  },

  slow_disk.get_c,

  slow_disk.get_d,

  slow_disk.get_e,

  function (results) {
    var sum = results.reduce(function (sum, val) { return sum + val; });

    exhibit_e.report(&amp;#39;sum = &amp;#39; + sum);
  }
);&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;That does the job, but I have two issues with the solution.&lt;/p&gt;

&lt;p&gt;First, the sequential indirect getters are messy, and they clearly repeat code. That issue can be solved with another helper function:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;:::javascript
function get_indirect(indirect_method) {
  var self = smarter_slow_disk;

  return function (callback) {
    async_helper.sequence(
      self[indirect_method],
      function (callback, results) {
        self[results[0]](function (val) { callback(val); });
      },
      function (results) {
        callback(results[1]);
      }
    );
  };
};&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The second issue with the parallel/sequence mix solution arises from the fact that we’re wasting time. If I can safely assume (of course we can; I defined the problem) that the values on my slow disk are static enough to be cached, we don’t need to make the same slow calls multiple times. But simple result caching only gets us half way.&lt;/p&gt;

&lt;p&gt;My problem was carefully designed to include a second call to get_e that is invoked while the first call to get_e is in the middle of its roundtrip. At the time the second function is called, we don’t have a cached response. We need a way to call the second callback when we receive the first result.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;:::javascript
var async_cache = function(obj) {

  var responses = {},
      waiting = {},
      caching_obj = {},
      func = null;

  caching_obj.prototype = obj;

  function wrap_method(method, func) {
    return function(callback) {
      if (responses[method]) {
        // We already have this result, invoke callback immediately.
        callback(responses[method]);
      } else if (waiting[method]) {
        // Someone else is waiting for this result. Just add
        // ourself to the waiting list.
        waiting[method].push(callback);
      } else {
        // No one has asked for this yet. Store the caller&amp;#39;s
        // callback on the waiting list and handle the response
        // callback by looping through the waiting list and
        // invoking all waiting callbacks.
        waiting[method] = [callback];
        func(function (val) {
          responses[method] = val;
          waiting[method].forEach(function(callback) {
            callback(val);
          });
          delete waiting[method];
        });
      }
    }
  }

  for (var method in obj) {
    func = obj[method];
    // Don&amp;#39;t try cache magic for non-functions
    if (typeof func === &amp;#39;function&amp;#39;) {
      caching_obj[method] = wrap_method(method, func);
    }
  }

  return caching_obj;
}&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The function above extends the object passed into it with async caching capabilities. It ensures that a slow asynchronous function call is only dispatched once. Repeated calls to the method either use a stored response or add their callback to a list of callbacks that will be invoked when the initial method calls back.&lt;/p&gt;

&lt;p&gt;Using both our indirect helper and the caching extension, the solution to the slow disk problem is now:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;:::javascript
var smarter_slow_disk = async_cache(slow_disk);

var exhibit_f = exhibit(&amp;#39;sequence/parallel mix with caching&amp;#39;);
async_helper.parallel(
  get_indirect(&amp;#39;get_a&amp;#39;),
  get_indirect(&amp;#39;get_b&amp;#39;),
  smarter_slow_disk.get_c,
  smarter_slow_disk.get_d,
  smarter_slow_disk.get_e,
  function (results) {
    var sum = results.reduce(function (sum, val) { return sum + val; });

    exhibit_f.report(&amp;#39;sum = &amp;#39; + sum);
  }
);&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id='node_doesnt_solve_your_problems'&gt;Node Doesn’t Solve Your Problems&lt;/h2&gt;

&lt;p&gt;At no point in this post did I write any complex, multi-threaded code. Such is the promise of Node. I will allow the reader to decide whether or not this exercise involved any complex, single-threaded code.&lt;/p&gt;

&lt;p&gt;Node doesn’t necessarily make it easier to solve difficult problems. The onus is still on the developer to identify and abstract away common async patterns. There are no freebies. Clean, maintainable, readable code still requires thoughtfulness and diligence. Or at least it does for less-than-experts like myself who want to try their hands at fast systems.&lt;/p&gt;</content>
  </entry>
  <entry>
    <title>Step One:  Put Your Node in a Box</title>
    <link rel="alternate" href="/writings/2011/02/21/step-one-put-your-node-in-a-box/"/>
    <id>/writings/2011/02/21/step-one-put-your-node-in-a-box/</id>
    <published>2011-02-21T00:00:00Z</published>
    <updated>2011-02-21T00:00:00Z</updated>
    <author>
      <name>Steve Lloyd</name>
    </author>
    <summary type="html">&lt;p&gt;In my &lt;a href='http://repeatingbeats.com/randlog/2011/02/03/a-slightly-less-intolerable-php-dev-environment-with-vagrant-and-chef/'&gt;last post&lt;/a&gt;, I extolled the virtues of isolating repeatable, versionable development environments in &lt;a href='http://www.virtualbox.org/'&gt;VirtualBox&lt;/a&gt; virtual machines with &lt;a href='http://vagrantup.com/'&gt;Vagrant&lt;/a&gt;. I find this to be particularly important in a rapidly changing software ecosystem like that of &lt;a href='http://nodejs.org/'&gt;Node.js&lt;/a&gt;. Node has quickly advanced to the latest 0.4 branch, and the API (though now ‘stable’) has been something of a moving target. Combine this with the relatively poor state of documentation for third party Node libraries, and it is quite easy to get into version hell on a development machine.&lt;/p&gt;</summary>
    <content type="html">&lt;p&gt;In my &lt;a href='http://repeatingbeats.com/randlog/2011/02/03/a-slightly-less-intolerable-php-dev-environment-with-vagrant-and-chef/'&gt;last post&lt;/a&gt;, I extolled the virtues of isolating repeatable, versionable development environments in &lt;a href='http://www.virtualbox.org/'&gt;VirtualBox&lt;/a&gt; virtual machines with &lt;a href='http://vagrantup.com/'&gt;Vagrant&lt;/a&gt;. I find this to be particularly important in a rapidly changing software ecosystem like that of &lt;a href='http://nodejs.org/'&gt;Node.js&lt;/a&gt;. Node has quickly advanced to the latest 0.4 branch, and the API (though now ‘stable’) has been something of a moving target. Combine this with the relatively poor state of documentation for third party Node libraries, and it is quite easy to get into version hell on a development machine.&lt;/p&gt;

&lt;h2 id='introducing_nodebox'&gt;Introducing NodeBox&lt;/h2&gt;

&lt;p&gt;&lt;a href='https://github.com/repeatingbeats/nodebox'&gt;NodeBox&lt;/a&gt; uses a set of &lt;a href='http://www.opscode.com/chef/'&gt;Chef&lt;/a&gt; cookbooks and a custom Vagrant configuration to automatically create VMs for Node application development. The NodeBox repository is intended to be an independent submodule of an application, and I put together a &lt;a href='https://github.com/repeatingbeats/nodebox-example'&gt;basic “Hello World” example app&lt;/a&gt; to demonstrate.&lt;/p&gt;

&lt;p&gt;Here’s all it takes to get started with NodeBox (This requires Vagrant and its dependencies. &lt;a href='http://vagrantup.com/docs/getting-started/index.html'&gt;See here&lt;/a&gt;. NodeBox requires Vagrant 0.7 or higher and VirtualBox 0.4.x):&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ git clone git://github.com/repeatingbeats/nodebox-example.git --recursive
$ cd nodebox-example/nodebox
$ vagrant up&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;After Vagrant takes a few minutes to do its magic, point your browser at &lt;code&gt;http://localhost:8000&lt;/code&gt; to see the application in action. The Node app serving this response can be found in &lt;code&gt;app.js&lt;/code&gt; in the toplevel &lt;code&gt;nodebox-example&lt;/code&gt; directory:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;:::javascript
var fs = require(&amp;#39;fs&amp;#39;),
    http = require(&amp;#39;http&amp;#39;)
;

var config = JSON.parse(fs.readFileSync(__dirname + &amp;#39;/nodebox.json&amp;#39;));
var env = config.environment;
var port = config.app_port || (env == &amp;quot;production&amp;quot; ? 8080: 80);

http.createServer(function (req, res) {
  res.writeHead(200, {&amp;#39;Content-Type&amp;#39;: &amp;#39;text/plain&amp;#39;});
    res.end(&amp;#39;Hello World, I Am A NodeBox\n&amp;#39;);
}).listen(port);
console.log(&amp;quot;Server listening on port: &amp;quot; + port);&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This simple application reads configuration variables out of &lt;code&gt;nodebox.json&lt;/code&gt; and responds to all requests with the Hello World string.&lt;/p&gt;

&lt;h2 id='isnt_it_easier_to_just_build_node_and_get_on_with_it'&gt;Isn’t It Easier to Just Build Node and Get On With It?&lt;/h2&gt;

&lt;p&gt;To get started? Yes. But my goal here isn’t to build the most complex Hello World contraption imaginable. I’m trying to make it easy to mix and match Node versions, Node modules, server configurations, and eventually databases. I’m trying to make it easy to do this in a way that isolates each environment so that when I find one that works, I have a setup that’s ready to roll into production. I don’t want or need eighteen kajillion competing libraries on my laptop. NodeBox is a tool that lets me easily spin up a new environment, and I can blow it up whenever I feel like it.&lt;/p&gt;

&lt;h2 id='nodebox_configuration'&gt;NodeBox Configuration&lt;/h2&gt;

&lt;p&gt;NodeBox’s configuration can be adjusted using a required &lt;code&gt;nodebox.json&lt;/code&gt; in the application’s root directory. Here’s the configuration for &lt;code&gt;nodebox-example&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;{
  &amp;quot;app_name&amp;quot;: &amp;quot;nodebox-example&amp;quot;,
  &amp;quot;environment&amp;quot;: &amp;quot;production&amp;quot;,
  &amp;quot;app_port&amp;quot;: 8080,
  &amp;quot;host_port&amp;quot;: 8000,
  &amp;quot;modules&amp;quot;: [ &amp;quot;express&amp;quot;,
               &amp;quot;nodeunit&amp;quot;,
               &amp;quot;mongoose&amp;quot; ],
  &amp;quot;node_version&amp;quot;: &amp;quot;0.4.0&amp;quot;,
  &amp;quot;npm_version&amp;quot;: &amp;quot;0.3.0-9&amp;quot;
}&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Most of the options are self-explanatory. &lt;code&gt;app_port&lt;/code&gt; is the port on the VM that Node listens on. This should be set to 80 if the environment is “development”. &lt;code&gt;host_port&lt;/code&gt; is the port on on the host machine that forwards to port 80 on the VM. &lt;code&gt;modules&lt;/code&gt; is an array of node modules that will be installed by NPM on the VM.&lt;/p&gt;

&lt;h2 id='productionish_nodebox'&gt;Production-ish NodeBox&lt;/h2&gt;

&lt;p&gt;NodeBox has recipes for both Development and Production server configurations. The Production recipe comes with the caveat that it is a work in progress, but it contains some basic extra features that make more sense on a production server than on a development server. NodeBox defaults to Production, mostly because the Production box takes fewer steps to get from &lt;code&gt;git clone&lt;/code&gt; to Hello World.&lt;/p&gt;

&lt;p&gt;The Production recipe hides Node behind the &lt;a href='http://nginx.org/'&gt;Nginx&lt;/a&gt; web server, which proxies requests to Node on an upstream port. Additionally, &lt;a href='http://upstart.ubuntu.com/'&gt;upstart&lt;/a&gt; is used to daemonize the Node process and allow easy starting and stopping of the app. The recipe starts the app during the initial chef configuration, but if you need to restart you can do this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ cd /path/to/nodebox-example/nodebox
$ vagrant ssh
$ sudo stop nodebox-example
$ sudo start nodebox-example&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The Production NodeBox also uses Monit to restart the application when it dies. There are certainly plenty of other options for monitoring Node processes. I borrowed mine &lt;a href='http://howtonode.org/deploying-node-upstart-monit'&gt;from here&lt;/a&gt;, with some slight modifications and of course the Chef templating.&lt;/p&gt;

&lt;h2 id='development_nodebox'&gt;Development NodeBox&lt;/h2&gt;

&lt;p&gt;Getting started with the development NodeBox requires an extra couple steps:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ git clone git://github.com/repeatingbeats/nodebox-example.git --recursive
$ cd nodebox-example&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;You’ll need to modify &lt;code&gt;nodebox.json&lt;/code&gt; slightly:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;{
  ...
  &amp;quot;environment&amp;quot;: &amp;quot;development&amp;quot;,
  &amp;quot;app_port&amp;quot;: 80,
  ...
}&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Next:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ cd nodebox
$ vagrant up
$ vagrant ssh&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Finally, now that you’re in a shell on the VM:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ cd /var/www/nodebox-example
$ sudo supervisor -p app.js -w app.js&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Sudo is required so that Node can listen on port 80. Do this in the safety of your own VM! Back on the host machine, point your browser at &lt;code&gt;http://localhost:8000&lt;/code&gt; once more. You should see the Hello World message. Now, change something in app.js. &lt;a href='https://github.com/isaacs/node-supervisor'&gt;Node-supervisor&lt;/a&gt; will detect the change, crash the app, and restart it. The next time you go to &lt;code&gt;http://localhost:8000&lt;/code&gt;, you’ll be able to see your new changes.&lt;/p&gt;

&lt;p&gt;Yes, the Development NodeBox takes a few more steps to get started, but for good reason. Starting Node from a shell on the VM lets you see your errors!&lt;/p&gt;

&lt;h2 id='what_now'&gt;What Now?&lt;/h2&gt;

&lt;p&gt;I’ve just walked you through how to get started with a basic Node application using NodeBox. Presumably, if you actually tried this, you might want to start building something. Feel free to poke through the &lt;a href='https://github.com/repeatingbeats/nodebox-example'&gt;nodebox-example&lt;/a&gt; and &lt;a href='https://github.com/repeatingbeats/nodebox'&gt;nodebox&lt;/a&gt; repositories to see what’s going on under the hood.&lt;/p&gt;

&lt;p&gt;The next step for NodeBox is going to be integration of persistence mechanisms. I’m envisioning an option in &lt;code&gt;nodebox.json&lt;/code&gt; that will tell Chef to do all the necessary setup to get one or more of Redis, MongoDB, MySQL, etc. up and running on the VM. Once there are persistence options, the production NodeBox will have everything it needs to start bootstrapping real deployments.&lt;/p&gt;

&lt;p&gt;If you’d like to be the very first to hear about future NodeBox developments intermixed with other inconsequential 140-character outbursts, you’ll probably want to &lt;a href='http://www.twitter.com/repeatingbeats'&gt;follow me on Twitter&lt;/a&gt;.&lt;/p&gt;</content>
  </entry>
  <entry>
    <title>A Slightly Less Intolerable PHP Dev Environment with Vagrant and Chef</title>
    <link rel="alternate" href="/writings/2011/02/03/a-slightly-less-intolerable-php-dev-environment-with-vagrant-and-chef/"/>
    <id>/writings/2011/02/03/a-slightly-less-intolerable-php-dev-environment-with-vagrant-and-chef/</id>
    <published>2011-02-03T00:00:00Z</published>
    <updated>2011-02-03T00:00:00Z</updated>
    <author>
      <name>Steve Lloyd</name>
    </author>
    <summary type="html">&lt;p&gt;Let’s get one thing out of the way: I am not a PHP guru. I have however, &lt;em&gt;wrestled&lt;/em&gt; with PHP in attempts to put my own stamp on my WordPress theme. Given my general lack of day-to-day PHP engagement, the first challenge in redesigning this site’s theme was figuring out what on earth I was using for a development environment the first time around. Some digging on the old MacBook revealed that the answer was &lt;a href='http://www.mamp.info/en/index.html'&gt;MAMP&lt;/a&gt;. I fired up the MAMP app, hit ‘Start Servers’, and … nothing happened.&lt;/p&gt;</summary>
    <content type="html">&lt;p&gt;Let’s get one thing out of the way: I am not a PHP guru. I have however, &lt;em&gt;wrestled&lt;/em&gt; with PHP in attempts to put my own stamp on my WordPress theme. Given my general lack of day-to-day PHP engagement, the first challenge in redesigning this site’s theme was figuring out what on earth I was using for a development environment the first time around. Some digging on the old MacBook revealed that the answer was &lt;a href='http://www.mamp.info/en/index.html'&gt;MAMP&lt;/a&gt;. I fired up the MAMP app, hit ‘Start Servers’, and … nothing happened.&lt;/p&gt;

&lt;p&gt;In a previous life I might have resigned myself to a few hours of turning the knobs on Apache and MySQL. After 3+ years of &lt;code&gt;port install whatever&lt;/code&gt;, &lt;code&gt;curl http://whizbang.org/install.sh | sh&lt;/code&gt;, and vanilla building from source, my veteran MacBook is somewhat cluttered. Apparently I never get around to &lt;code&gt;make uninstall&lt;/code&gt;.&lt;/p&gt;

&lt;h2 id='enter_vagrant'&gt;Enter Vagrant&lt;/h2&gt;

&lt;p&gt;Lately at work, I’ve been using &lt;a href='http://vagrantup.com/'&gt;Vagrant&lt;/a&gt; to sandbox my per-project development environments onto their own VMs. Vagrant is a tool to help create and provision &lt;a href='http://www.virtualbox.org/'&gt;VirtualBox&lt;/a&gt; machines. The short list of reasons why this is a good idea:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;The development environment can be isolated from all the other junk that accumulates on my primary computer.&lt;/p&gt;
&lt;/li&gt;

&lt;li&gt;
&lt;p&gt;The development environment can be tuned to match a production server environment as closely as possible.&lt;/p&gt;
&lt;/li&gt;

&lt;li&gt;
&lt;p&gt;Provisioning scripts define the machine configuration in code. This means the configuration is &lt;em&gt;repeatable&lt;/em&gt; and &lt;em&gt;versionable&lt;/em&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Getting started with Vagrant is easy. All you need is ruby, the gem command line tool, and Virtualbox. The latest-and-greatest Vagrant requires Virtualbox 4.0.x, which you can grab &lt;a href='http://www.virtualbox.org/wiki/Downloads'&gt;over here&lt;/a&gt;. If you need more information for Ruby and RubyGems, you may want to check out the links on Vagrant’s &lt;a href='http://vagrantup.com/docs/getting-started/index.html'&gt;getting started page&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Once you have those dependencies, install the vagrant gem:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ gem install vagrant&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Next, download a ‘base box’. This command fetches the base box for Ubuntu 10.04 (32 bit):&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ vagrant box add ubuntu-lucid-32 http://files.vagrantup.com/lucid32.box&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This downloads the base box and stores it at &lt;code&gt;/~/.vagrant/boxes&lt;/code&gt;, and you can then reference it locally with vagrant as &lt;code&gt;ubuntu-lucid-32&lt;/code&gt; or whatever you decided to call it.&lt;/p&gt;

&lt;h2 id='project_setup'&gt;Project Setup&lt;/h2&gt;

&lt;p&gt;I have both my &lt;code&gt;rb2.0&lt;/code&gt; WordPress theme and my vagrant configuration in a repository laid out like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;-repeatingbeats.com/
  -rb2.0/
    -comments.php
    -footer.php
    -functions.php
    -header.php
    and so forth ...
  -vagrant/
    -cookbooks/&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The first step is to initialize the vagrant folder:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ cd /path/to/repeatingbeats.com/vagrant
$ vagrant init&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This creates a default Vagrantfile that is helpfully commented with various configuration options. The Vagrantfile uses Ruby code to configure the virtual machine. Here’s what my Vagrantfile looks like for the WordPress project:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;:::ruby
Vagrant::Config.run do | config |

  # Use our base ubuntu box
  config.vm.box = &amp;quot;ubuntu-lucid-32&amp;quot;

  # Forward port 8080 on the host to port 80 on the VM
  config.vm.forward_port &amp;quot;http&amp;quot;, 80, 8080

  # Map project source folder to VM
  config.vm.share_folder(&amp;quot;repeatingbeats.com&amp;quot;,
                         &amp;quot;/var/www/wordpress/wp-content/themes/rb2.0&amp;quot;,
                         &amp;quot;../rb2.0&amp;quot;)

  # Provision with chef solo
  config.vm.provision :chef_solo do | chef |
    chef.cookbooks_path = &amp;quot;cookbooks&amp;quot;
    chef.add_recipe(&amp;quot;repeatingbeats.com&amp;quot;)
  end

end&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This configures the VM to use the ubuntu base box, sets up port forwarding so I’ll be able to view the WordPress site from a browser on the host machine, shares my WordPress theme’s source folder with the VM, and configures Chef Solo to manage the server provisioning.&lt;/p&gt;

&lt;h2 id='chef_cookbooks_and_the_metaphor_really_just_keeps_going'&gt;Chef, Cookbooks, and the Metaphor Really Just Keeps Going&lt;/h2&gt;

&lt;p&gt;&lt;a href='http://opscode.com/chef/'&gt;Chef&lt;/a&gt; is a server configuration management tool. Server configuration (e.g. packages, services, directories, users, etc.) is described in code. It would take a full blog post to describe the small subset of Chef that I have thus far uncovered, so just head over to the &lt;a href='http://wiki.opscode.com/display/chef/Home'&gt;Chef Wiki&lt;/a&gt; if you want to learn more.&lt;/p&gt;

&lt;p&gt;A closer look at the vagrant folder:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;-repeatingbeats.com/
  -vagrant/
    -Vagrantfile
    -cookbooks/
      -apache2/
      -mysql/
      -openssl/
      -php/
      -repeatingbeats.com/
      -wordpress/&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Uhoh. This is starting to look like a lot of work! Each cookbook directory contains instructions (ahem … “recipes”) for configuring that aspect of the server. Luckily, most of the work was already done for me and I merely had to fork the &lt;a href='https://github.com/opscode/cookbooks'&gt;Opscode cookbook repository&lt;/a&gt; to get everything except the custom repeatingbeats.com cookbook.&lt;/p&gt;

&lt;p&gt;The repeatingbeats.com cookbook ties it all together. It’s only a single file: &lt;code&gt;cookbooks/repeatingbeats.com/recipes/default.rb&lt;/code&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;:::ruby
# Optional packages that I like to have installed
%w{vim man-db git-core}.each do | pkg |
  package pkg
end

# Run apt-get update before the chef convergence stage
r = execute &amp;quot;apt-get update&amp;quot; do
  user &amp;quot;root&amp;quot;
  command &amp;quot;apt-get update&amp;quot;
  action :nothing
end
r.run_action(:run)

include_recipe &amp;quot;wordpress&amp;quot;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The wordpress recipe does the heavy lifting. It installs apache2, mysql, and php, and it drops a WordPress install at a default location of &lt;code&gt;/var/www/wordpress&lt;/code&gt; on the VM. Conveniently, my shared theme source folder lands in exactly the right spot: &lt;code&gt;/var/www/wordpress/wp-content/themes/rb2.0&lt;/code&gt;.&lt;/p&gt;

&lt;h2 id='hello_wordpress_can_i_see_my_site_already'&gt;Hello WordPress (Can I See My Site Already?)&lt;/h2&gt;

&lt;p&gt;Everything is now ready to go. Let’s start the VM:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ cd /path/to/repeatingbeats.com/vagrant
$ vagrant up&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Don’t hold your breath. The startup and provisioning can take some time. Once it’s done, you can ssh into the new VM to poke around with a simple:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ vagrant ssh&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;If you’re playing along at home, you should be able to find the WordPress folder in &lt;code&gt;/var/www/wordpress&lt;/code&gt;, and you can &lt;code&gt;ps&lt;/code&gt; to your heart’s content to verify that Apache and MySQL are up and running.&lt;/p&gt;

&lt;h2 id='i_meant_in_a_browser'&gt;I Meant In a Browser&lt;/h2&gt;

&lt;p&gt;Ok! Open up your favorite browser and navigate to the WordPress install page at &lt;code&gt;http://localhost:8080/wordpress/wp-admin/install.php&lt;/code&gt;. You should be able to quickly finish the install, configure the admin user, and get logged in to the admin page. Click ‘Appearance’ in the left navigation column, and your fancy theme should be listed as one of the available themes. Click ‘Activate’, then go to the home page at &lt;code&gt;http://localhost:8080/wordpress&lt;/code&gt;. Here’s what I see:&lt;/p&gt;

&lt;p&gt;&lt;img alt='Wordpress Theme Screenshot Running on Vagrant VM' src='/images/rsz_theme.png' /&gt;&lt;/p&gt;

&lt;h2 id='but_didnt_this_seem_like_a_lot_of_work'&gt;But Didn’t This Seem Like a Lot of Work?&lt;/h2&gt;

&lt;p&gt;Admittedly, this probably didn’t save much time in terms of initial environment setup. I probably could have cajoled the MacBook into running WordPress with a comparable level of effort.&lt;/p&gt;

&lt;p&gt;However, what about the next time I want to tweak the site? All I need to do is clone my repository and run vagrant up. I’m right back into my development environment with no effort at all.&lt;/p&gt;

&lt;p&gt;If I want to blow it up and start over, I just write a new Chef recipe. If I’m on another machine, I can get right into the same environment just as easily once I’ve obtained the minimal dependencies for Vagrant. No need to mess with Apache and MySQL just to test some changes to the footer.&lt;/p&gt;

&lt;p&gt;As an added bonus, I got to do this on my MacBook:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ port uninstall php5&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id='further_reading'&gt;Further Reading&lt;/h2&gt;

&lt;p&gt;&lt;a href='http://www.vagrantup.com/'&gt;Vagrant Home Page&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href='http://wiki.opscode.com/display/chef/Home'&gt;Chef Wiki&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href='http://codex.wordpress.org/Theme_Development'&gt;WordPress Theme Development&lt;/a&gt;&lt;/p&gt;</content>
  </entry>
  <entry>
    <title>Blog 2.0 - What I Did and How I Did It</title>
    <link rel="alternate" href="/writings/2011/01/29/blog-2-0-what-i-did-and-how-i-did-it/"/>
    <id>/writings/2011/01/29/blog-2-0-what-i-did-and-how-i-did-it/</id>
    <published>2011-01-29T00:00:00Z</published>
    <updated>2011-01-29T00:00:00Z</updated>
    <author>
      <name>Steve Lloyd</name>
    </author>
    <summary type="html">&lt;p&gt;It is an indisputable fact [1] that there are 152 million blogs on the internet. Even if one assumes that &lt;a href='http://www.nytimes.com/2009/06/07/fashion/07blogs.html?_r=1&amp;amp;hpw'&gt;95% of these blogs are abandoned&lt;/a&gt;, that still leaves a healthy 7.6 million active bloggy destinations.&lt;/p&gt;</summary>
    <content type="html">&lt;p&gt;It is an indisputable fact [1] that there are 152 million blogs on the internet. Even if one assumes that &lt;a href='http://www.nytimes.com/2009/06/07/fashion/07blogs.html?_r=1&amp;amp;hpw'&gt;95% of these blogs are abandoned&lt;/a&gt;, that still leaves a healthy 7.6 million active bloggy destinations.&lt;/p&gt;

&lt;p&gt;There is always someone with better ideas. There is always someone with more correct instructions on how to get MySQL to do what you want it to do. There is always someone more entertaining. In fact, there is probably even someone &lt;a href='http://soberbuildengineer.com/blog/'&gt;so good at footnotes&lt;/a&gt; that it makes you want to avoid using them out of sheer inadequacy [2].&lt;/p&gt;

&lt;p&gt;So why blog? Why now, after intensely focusing on &lt;em&gt;not&lt;/em&gt; blogging for about as long as this blog has existed?&lt;/p&gt;

&lt;p&gt;I don’t do much writing anymore. I certainly do plenty of typing, some of which actually involves communicating by stringing together combinations of English words in a passably intelligible fashion. But the majority of this communication occurs in short IRC/AIM bursts, and actually writing demands practice that I haven’t been getting.&lt;/p&gt;

&lt;p&gt;My loose goal for Blog 2.0 is to write frequently and to generally try to keep to the theme of “What I Did and How I Did It” [3]. While &lt;a href='http://stackoverflow.com/'&gt;Stack Overflow&lt;/a&gt; is a great resource for targeted programming questions, I’ve found random blogs to be the most reliable source of “How To” manuals for various tasks and problems. Code documentation is almost invariably written by people too close to the actual code [4], and sometimes the thrilling blogged account of &lt;em&gt;how someone actually got the darn thing to work&lt;/em&gt; is essential. Thus, there is a small possibility that accounts of how I got something to work will prove useful. But that is not the only motivation.&lt;/p&gt;

&lt;p&gt;It can be easy to gloss over small things that aren’t completely understood when there are no obvious negative side effects. That line of code you don’t really grok might just remain ungrokked. I generally walk away with a much greater understanding of how something works after I’ve been forced to explain it to someone else. Writing about What I Did and How I Did It promotes that higher level of understanding. As an added benefit, the internet is crawling with people who are dying to tell you why you are wrong. I’m eager to know why I’m wrong [5].&lt;/p&gt;

&lt;p&gt;Naturally, my desire to actually legitimately try to blog was blocked by my compelling need to update this bit-rotting site’s theme. So that’s What I Did.&lt;/p&gt;

&lt;p&gt;(psst … you should &lt;a href='http://www.twitter.com/repeatingbeats'&gt;follow me on Twitter&lt;/a&gt;) [6]&lt;/p&gt;

&lt;p&gt;&lt;em&gt;footnotes&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;[1] Where we define “fact” as “a statistic published within the last month that was in the first page of google search results” (&lt;a href='http://royal.pingdom.com/2011/01/12/internet-2010-in-numbers/'&gt;see here&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;[2] Luckily, that has never stopped me from doing anything.&lt;/p&gt;

&lt;p&gt;[3] This carries an implicit goal of “DO THINGS”.&lt;/p&gt;

&lt;p&gt;[4] Blogging also appears to be a good outlet for expressing correct opinions.&lt;/p&gt;

&lt;p&gt;[5] To clarify, I’m generally only interested in knowing when I’m technically wrong. My opinions tend to be indisputably correct.&lt;/p&gt;

&lt;p&gt;[6] I feel less self-conscious about self-promotion when I do things like provide footnotes detailing my general feelings of self-consciousness about self-promotion.&lt;/p&gt;</content>
  </entry>
</feed>
