<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	xmlns:georss="http://www.georss.org/georss" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" xmlns:media="http://search.yahoo.com/mrss/"
	>

<channel>
	<title>Magic Scaling Sprinkles</title>
	<atom:link href="http://magicscalingsprinkles.wordpress.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://magicscalingsprinkles.wordpress.com</link>
	<description>Just another WordPress.com weblog</description>
	<lastBuildDate>Sat, 09 Jul 2011 22:38:44 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.com/</generator>
<cloud domain='magicscalingsprinkles.wordpress.com' port='80' path='/?rsscloud=notify' registerProcedure='' protocol='http-post' />
<image>
		<url>http://s2.wp.com/i/buttonw-com.png</url>
		<title>Magic Scaling Sprinkles</title>
		<link>http://magicscalingsprinkles.wordpress.com</link>
	</image>
	<atom:link rel="search" type="application/opensearchdescription+xml" href="http://magicscalingsprinkles.wordpress.com/osd.xml" title="Magic Scaling Sprinkles" />
	<atom:link rel='hub' href='http://magicscalingsprinkles.wordpress.com/?pushpress=hub'/>
		<item>
		<title>Responsible Technology Journalism</title>
		<link>http://magicscalingsprinkles.wordpress.com/2010/07/08/responsible-technology-journalism/</link>
		<comments>http://magicscalingsprinkles.wordpress.com/2010/07/08/responsible-technology-journalism/#comments</comments>
		<pubDate>Thu, 08 Jul 2010 07:23:01 +0000</pubDate>
		<dc:creator>nkallen</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://magicscalingsprinkles.wordpress.com/?p=552</guid>
		<description><![CDATA[The biggest weakness of the tech journalism audience, a mental cancer, is lacking enthusiasm for new technology and bold ventures&#8230; You wonder why people even read Techcrunch when they write comments like &#8216;Twitter is a waste of time&#8217;, &#8216;why even bother with Foursquare when Facebook will just kill them&#8217;, etc. Enthusiasm, and even partisanship, is [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=magicscalingsprinkles.wordpress.com&amp;blog=5347219&amp;post=552&amp;subd=magicscalingsprinkles&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>The biggest weakness of the tech journalism audience, <a href="http://techcrunch.com/2010/06/27/staying-credulous-on-not-letting-being-40-get-in-the-way/">a mental cancer</a>, is lacking enthusiasm for new technology and bold ventures&#8230;</p>
<p>You wonder why people even read Techcrunch when they write comments like &#8216;Twitter is a waste of time&#8217;, &#8216;why even bother with Foursquare when Facebook will just kill them&#8217;, etc.</p>
<p>Enthusiasm, and even partisanship, is not what I decry as the lack of objective tech journalism. It isn&#8217;t like to political journalism; it better resembles scientific journalism: describing the latest images from the Hubble telescope, communicating a sense of wonder at the cosmos. The vocation of tech journalists should be to educate the public. And being enthusiastic is probably necessary to be effective.</p>
<p>I do think journalists should consider themselves public servants. What I dislike is sensationalism, gossip, and a lack of depth. Merely announcing how much money a company has raised, what features a product offers &#8211; with this journalists are failing to perform their duty.</p>
<p>It reminds me of Le Petit Prince:</p>
<blockquote><p>Grown-ups like numbers. When you tell them about a new friend, they never ask questions about what really matters. They never ask: &#8220;What does his voice sound like?&#8221; &#8220;What games does he like best?&#8221; &#8220;Does he collect butterflies?&#8221;. They ask: &#8220;How old is he?&#8221; &#8220;How many brothers does he have?&#8221; &#8220;How much does he weigh?&#8221; &#8220;How much money does his father make?&#8221; Only then do they think they know him. </p></blockquote>
<p>I work in a very narrow field that has unfortunate occasions of intense interest. MG Siegler wrote a terrible piece about an outage that Foursquare suffered. The thesis of the article: these clowns can&#8217;t keep it up when EC2 goes down on them! But he doesn&#8217;t ask the good questions: why did they go down when only one region of EC2 crashed? How do you do multi-region (i.e., multi-master) data-centers? How does a ramen-eating startup deal with suddenly being of historic significance and problems that took google 5 years to solve? Has Foursquare&#8217;s unusual technical choices (e.g., EC2, Scala) helped them innovate or increased risk or both?</p>
<p>This would not require long-form journalism. Just ask one question and get the opinion of a few experts. Or just ask a meaningful question and don&#8217;t try to answer it. This is not: &#8220;Update: 4 hours later Foursquare returns. Will they be another Twitter?&#8217;</p>
<p>Perhaps I&#8217;m bitter because I work for Twitter.</p>
<p>The audience, of course, lacks reading comprehension skills and any genuine empathy for machines. So there is this unfortunate paradox that the role of the press is to educate the public but the press will not do so until the public demands better and the public is too incompetent to demand anything worthwhile.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/magicscalingsprinkles.wordpress.com/552/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/magicscalingsprinkles.wordpress.com/552/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/magicscalingsprinkles.wordpress.com/552/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/magicscalingsprinkles.wordpress.com/552/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/magicscalingsprinkles.wordpress.com/552/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/magicscalingsprinkles.wordpress.com/552/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/magicscalingsprinkles.wordpress.com/552/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/magicscalingsprinkles.wordpress.com/552/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/magicscalingsprinkles.wordpress.com/552/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/magicscalingsprinkles.wordpress.com/552/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/magicscalingsprinkles.wordpress.com/552/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/magicscalingsprinkles.wordpress.com/552/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/magicscalingsprinkles.wordpress.com/552/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/magicscalingsprinkles.wordpress.com/552/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=magicscalingsprinkles.wordpress.com&amp;blog=5347219&amp;post=552&amp;subd=magicscalingsprinkles&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://magicscalingsprinkles.wordpress.com/2010/07/08/responsible-technology-journalism/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/d9914cfbec64060f4053fc221a2a7536?s=96&#38;d=monsterid&#38;r=R" medium="image">
			<media:title type="html">nkallen</media:title>
		</media:content>
	</item>
		<item>
		<title>2010 Modularity Olympics</title>
		<link>http://magicscalingsprinkles.wordpress.com/2010/02/16/2010-modularity-olympics/</link>
		<comments>http://magicscalingsprinkles.wordpress.com/2010/02/16/2010-modularity-olympics/#comments</comments>
		<pubDate>Tue, 16 Feb 2010 06:59:28 +0000</pubDate>
		<dc:creator>nkallen</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://magicscalingsprinkles.wordpress.com/?p=528</guid>
		<description><![CDATA[This is a contest, open to programming languages from all nations, to write modular and extensible code to solve the following problem: Implement a service that can run queries on a database. The Challenge Sounds simple right? Wrong! A programmer without control over the source-code of that service must be able to later add enhancements [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=magicscalingsprinkles.wordpress.com&amp;blog=5347219&amp;post=528&amp;subd=magicscalingsprinkles&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>This is a contest, open to programming languages from all nations, to write modular and extensible code to solve the following problem: Implement a service that can run queries on a database.</p>
<h2>The Challenge</h2>
<p>Sounds simple right? Wrong! A programmer without control over the source-code of that service must be able to later add enhancements such as statistics collecting, timeouts, memoization, and so forth. There are a few more requirements:</p>
<ul>
<li>the &#8220;enhancements&#8221; must be specified in a configuration object which is consumed at run-time (e.g., it could be based on user-input).</li>
<li>The enhancements are ordered (stats collecting wraps timeouts, not the other way around) but it must be possible to reverse the order of the enhancements at run-time.</li>
<li>The enhancements must be &#8220;surgical&#8221; and not &#8220;global&#8221;. That is, it must be possible to <b>simultaneously</b> have two query services, one reversed and one not reversed, and even have a query service without any enhancements.</li>
<li>The code must be thread-safe or support using concurrency by some means. The same query service can be used by multiple threads as well as multiple threads with different query services.
</ul>
<p>Most programming contests emphasize things that are not modularity. This contest emphasizes things that <b>are</b> modularity. And its the olympics and don&#8217;t you want to be olympic? So go ahead and prove to the world that Design Patterns are no longer necessary, or that Haskell is the raddest thing since <a href="http://www.imdb.com/title/tt0091817/">the movie Rad</a>, or that Peanut Butter is better than Jelly. This is much more fun than inflamatory blog posts and angry reddit comments, yes? Yes.</p>
<h2>Context</h2>
<p>Please read my blog post on <a href="http://magicscalingsprinkles.wordpress.com/2010/02/08/why-i-love-everything-you-hate-about-java/">modularity techniques in Scala</a> and various responses (<a href="http://romanroe.blogspot.com/2010/02/why-i-hate-everything-you-love-about.html">in Clojure</a>, <a href="http://yehudakatz.com/2010/02/15/abstractqueryfactoryfactories-and-alias_method_chain-the-ruby-way/">in Ruby</a>, <a href="http://avdi.org/devblog/2010/02/09/everything-you-love-about-java-is-everything-i-love-about-good-design/">in Ruby again</a>)</p>
<h2>Languages &amp; Techniques</h2>
<p>You can use any programming language you like (functional, OO, stack-based) and any techniques you like. Your main goal should be clarity and flexibility. Terseness is valuable where it adds to clarity. Creative and unusual solutions are welcome, though. Try to implement all of the functionality (including transactions) of <a href="http://gist.github.com/304913">the sample solution</a>.</p>
<h2>How to Play</h2>
<p>Fork <a href="http://gist.github.com/304913">this gist</a>. Your program must produce the same output as mine (included below). I will collect all forks at link them here (it may take me a while, so please be patient).</p>
<h2>Sample Program</h2>
<p>I&#8217;ve tricked out some Factories and wrote <a href="http://gist.github.com/304913">this little diddy in Ruby</a>:</p>
<pre>
config = [
  [:memoizing, []],
  [:timing_out, [2.seconds]],
  [:stats_collecting, [Stats.new]]
]
query_factory = config.inject(Query) do |factory, (decorator_name, settings)|
  "#{decorator_name.to_s.classify}QueryFactory".constantize.new(factory, *settings)
end

[query_factory, ReversingQueryFactory.new(query_factory)].each do |qf|
  query_evaluator = QueryEvaluator.new(ConnectionPool.new(20), qf)
  query_evaluator.transaction do |t|
    t.select("SELECT ... FROM ... FOR UPDATE ...")
    t.execute("INSERT ...")
    t.execute("INSERT ...")
  end
  puts
end
</pre>
<h2>Sample Output</h2>
<p>Note the reversing order of the enhancements and the memoization of Query instantiation:</p>
<pre>
Forward:
Instantiating Query Object
Selecting SELECT ... FROM ... FOR UPDATE ... on #
Did not timeout! Yay fast database!
Measured select at 1.00 seconds
Instantiating Query Object
Executing INSERT ... on #
Did not timeout! Yay fast database!
Measured execute at 1.00 seconds
Executing INSERT ... on #
Did not timeout! Yay fast database!
Measured execute at 1.00 seconds

Backward:
Instantiating Query Object
Selecting SELECT ... FROM ... FOR UPDATE ... on #
Measured select at 1.00 seconds
Did not timeout! Yay fast database!
Instantiating Query Object
Executing INSERT ... on #
Measured execute at 1.00 seconds
Did not timeout! Yay fast database!
Executing INSERT ... on #
Measured execute at 1.00 seconds
Did not timeout! Yay fast database!
</pre>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/magicscalingsprinkles.wordpress.com/528/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/magicscalingsprinkles.wordpress.com/528/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/magicscalingsprinkles.wordpress.com/528/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/magicscalingsprinkles.wordpress.com/528/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/magicscalingsprinkles.wordpress.com/528/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/magicscalingsprinkles.wordpress.com/528/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/magicscalingsprinkles.wordpress.com/528/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/magicscalingsprinkles.wordpress.com/528/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/magicscalingsprinkles.wordpress.com/528/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/magicscalingsprinkles.wordpress.com/528/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/magicscalingsprinkles.wordpress.com/528/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/magicscalingsprinkles.wordpress.com/528/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/magicscalingsprinkles.wordpress.com/528/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/magicscalingsprinkles.wordpress.com/528/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=magicscalingsprinkles.wordpress.com&amp;blog=5347219&amp;post=528&amp;subd=magicscalingsprinkles&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://magicscalingsprinkles.wordpress.com/2010/02/16/2010-modularity-olympics/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/d9914cfbec64060f4053fc221a2a7536?s=96&#38;d=monsterid&#38;r=R" medium="image">
			<media:title type="html">nkallen</media:title>
		</media:content>
	</item>
		<item>
		<title>The Anatomy of a Whale</title>
		<link>http://magicscalingsprinkles.wordpress.com/2010/02/10/the-anatomy-of-a-whale/</link>
		<comments>http://magicscalingsprinkles.wordpress.com/2010/02/10/the-anatomy-of-a-whale/#comments</comments>
		<pubDate>Wed, 10 Feb 2010 06:47:44 +0000</pubDate>
		<dc:creator>nkallen</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://magicscalingsprinkles.wordpress.com/?p=505</guid>
		<description><![CDATA[Over on the Twitter Engineering Blog, Ed Ceaser and I posted an article about how we debugged a production incident on Twitter.com. It talks about what causes what has become known as &#8220;The Fail Whale&#8221; and other goodness. It&#8217;s written for a non-technical/semi-technical audience. For the hardcore, it&#8217;s probably the most detailed publication of Twitter [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=magicscalingsprinkles.wordpress.com&amp;blog=5347219&amp;post=505&amp;subd=magicscalingsprinkles&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Over on the Twitter Engineering Blog, Ed Ceaser and I posted <a href="http://engineering.twitter.com/2010/02/anatomy-of-whale.html">an article</a> about how we debugged a production incident on Twitter.com. It talks about what causes what has become known as &#8220;The Fail Whale&#8221; and other goodness. It&#8217;s written for a non-technical/semi-technical audience. For the hardcore, it&#8217;s probably the most detailed publication of Twitter traffic and efficiency data ever. Check it out!</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/magicscalingsprinkles.wordpress.com/505/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/magicscalingsprinkles.wordpress.com/505/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/magicscalingsprinkles.wordpress.com/505/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/magicscalingsprinkles.wordpress.com/505/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/magicscalingsprinkles.wordpress.com/505/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/magicscalingsprinkles.wordpress.com/505/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/magicscalingsprinkles.wordpress.com/505/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/magicscalingsprinkles.wordpress.com/505/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/magicscalingsprinkles.wordpress.com/505/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/magicscalingsprinkles.wordpress.com/505/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/magicscalingsprinkles.wordpress.com/505/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/magicscalingsprinkles.wordpress.com/505/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/magicscalingsprinkles.wordpress.com/505/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/magicscalingsprinkles.wordpress.com/505/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=magicscalingsprinkles.wordpress.com&amp;blog=5347219&amp;post=505&amp;subd=magicscalingsprinkles&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://magicscalingsprinkles.wordpress.com/2010/02/10/the-anatomy-of-a-whale/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/d9914cfbec64060f4053fc221a2a7536?s=96&#38;d=monsterid&#38;r=R" medium="image">
			<media:title type="html">nkallen</media:title>
		</media:content>
	</item>
		<item>
		<title>Why I love everything you hate about Java</title>
		<link>http://magicscalingsprinkles.wordpress.com/2010/02/08/why-i-love-everything-you-hate-about-java/</link>
		<comments>http://magicscalingsprinkles.wordpress.com/2010/02/08/why-i-love-everything-you-hate-about-java/#comments</comments>
		<pubDate>Mon, 08 Feb 2010 23:56:29 +0000</pubDate>
		<dc:creator>nkallen</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://magicscalingsprinkles.wordpress.com/?p=487</guid>
		<description><![CDATA[If you&#8217;re one of those hipster programmers who loves Clojure, Ruby, Scala, Erlang, or whatever, you probably deeply loathe Java and all of its giant configuration files and bloated APIs of AbstractFactoryFactoryInterfaces. I used to hate all that stuff too. But you know what? After working for all these months on these huge pieces of [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=magicscalingsprinkles.wordpress.com&amp;blog=5347219&amp;post=487&amp;subd=magicscalingsprinkles&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>If you&#8217;re one of those hipster programmers who loves Clojure, Ruby, Scala, Erlang, or whatever, you probably deeply loathe Java and all of its giant configuration files and bloated APIs of <code>AbstractFactoryFactoryInterfaces</code>. I used to hate all that stuff too. But you know what? After working for all these months on these huge pieces of Twitter infrastructure I&#8217;ve started to love the <code>AbstractFactoryFactories</code>.</p>
<p>Let me explain why. Consider this little Scala program. It uses &#8220;futures&#8221;, which are a way to schedule computation to be done in parallel from the main flow of a program. They are sometimes a natural way of modeling the most efficient scheduling of program execution. Usually you schedule in advance some expensive work that can be done in parallel and then you do something else in the meantime. Only when you really need the result of the original computation do you block and wait (and hopefully only very briefly since you scheduled the work way in advance!). Here is a &#8220;typical&#8221; Java-ish Futures library used from Scala:</p>
<pre>
    private val executor = new ThreadPoolExecutor(
      poolSize, maxPoolSize,
      keepAlive.inSeconds, TimeUnit.SECONDS,
      new LinkedBlockingQueue[Runnable],
      new NamedPoolThreadFactory(name))

    val future = new FutureTask {
      doSomeWork
    }

    executor.execute(future)</pre>
<p>If you come from a dynamic language like Ruby or Python you will probably have a visceral reaction like &#8220;Yeck! Look at all that horrible boilerplate. Convention over configuration!&#8221; Wouldn&#8217;t it be nice if you could just do something like:</p>
<pre>    val future = new Future {
      doSomeWork
    }</pre>
<p>It seems nice but its nicety is just an illusion. All that boilerplate is really important when you work at massive scale and where efficiency really matters. These magic numbers like the thread pool size and the kind of queue you use to schedule work can <strong>vastly</strong> impact the performance of your application. And the &#8220;right&#8221; configuration depends entirely on the nature of the problem you&#8217;re solving and how callers of this code behave. What all of this weird boilerplate provides is a way to configure the behavior of the system; it doesn&#8217;t assume there&#8217;s one right way of doing things. And that is precisely how <strong>modular</strong> software behaves: modular code is code designed to grow past the assumptions of just one user. Modularity really matters when your software isn&#8217;t a little throw-away program.</p>
<p>Twitter recently open-sourced <a href="http://github.com/nkallen/querulous">Querulous</a>, a minimal database querying library for Scala. We use it in several projects in Twitter, but it was designed principally to meet the extreme demands <code>FlockDB</code>, our distributed, fault-tolerant graph database. <code>FlockDB</code> demands extremely low-latency (sub millisecond) response times for individual queries. Any excessive indirection from an ORM would be unacceptable. Furthermore, because <code>FlockDB</code> processes tens of thousands of queries per second across dozens of shards, <code>FlockDB</code> must collect extensive statistics on the performance and health of the various shards in order to direct traffic to the most efficient place.</p>
<p>So <code>Querulous</code> was designed for querying databases at low latency, massive scale, and with easy operability. It has flexible timeouts, extensive logging, and rich statistics. But as <code>FlockDB</code> became more mature and sophisticated, the demands grew greater. We needed different health-check and timeout strategies in different contexts. It became clear that <code>Querulous</code> would need to be made extremely <strong>modular</strong> and extremely configurable to work at all.</p>
<p>So we set about to re-write <code>Querulous</code> using my favorite modularity techniques: Dependency Injection, Factories, and Decorators. In other words, everything you hate about Java.</p>
<h2>The design patterns of modularity</h2>
<p>In order for code to be modular it must have few hard-coded assumptions. In Object-Oriented software this means something very particular since the essence of an Object-Oriented program is that its structure is organized around the types of objects. Therefore, the most fundamental, anti-modular assumption in Object-Oriented software is the <strong>concrete type of objects</strong>. Any time you write <code>new MyClass</code> in your code you&#8217;ve hardcoded an assumption about the concrete class of the object you&#8217;re allocating. This makes it impossible, for example, for someone to later add logging around method invocations of that object, or timeouts, or whatever isn&#8217;t anticipated a priori.</p>
<p>In a very dynamic language like Ruby, open classes and method aliasing (e.g., <code>alias_method_chain</code>) mitigate this problem, but they don&#8217;t solve it. If you manipulate a class to add logging, all instances of that class will have logging; you can&#8217;t take a surgical approach and say &#8220;just objects instantiated in this context&#8221;. (<strong>Update: some people are asking &#8220;what about metaclasses? Metaclasses do not solve this problem at all because if you do not have control over the caller of <code>Foo.new</code> then you cannot later add new behavior to the metaclass; it has to be hardcoded at the site of manufacture. The point of this technique is to avoid knowing in advance what behavior you will add in, to make it configurable!</strong>)</p>
<p>There are standard design patterns to mitigate this, namely Dependency Injection, Factories, and Decorators. By injecting a Factory (a function that manufactures objects) as a parameter to a function that needs to create objects, you allow a programmer to later change his mind about what Factory to inject; and this means the programmer can change the concrete types of objects as his heart desires. And by using Decorators, the programmer can mix and match functionality easily, stack one thing on top of another like so many legos. Let&#8217;s look at an example.</p>
<p>Here I have a <code>Query</code> object, with methods like <code>#execute()</code>. I want to add timeouts around all queries. I start by creating a <code>QueryProxy</code> that routes all method invocations through an over-ridable method: <code>#delegate</code>:</p>
<pre>    abstract class QueryProxy(query: Query) extends Query {
      def select[A](f: ResultSet =&gt; A) = delegate(query.select(f))
      def execute() = delegate(query.execute())
      def cancel() = query.cancel()

      protected def delegate[A](f: =&gt; A) = f
    }</pre>
<p>Then, to implement timeouts, I create a <code>Query</code> Decorator:</p>
<pre>    class TimingOutQuery(timeout: Duration, query: Query) extends QueryProxy(query) {
      override def delegate[A](f: =&gt; A) = {
        try {
          Timeout(timeout) {
            f
          } {
            cancel()
          }
        } catch {
          case e: TimeoutException =&gt;
            throw new SqlTimeoutException
        }
      }
    }</pre>
<p>This Decorator delegates to the underlying query object the execution of the query, but it wraps that execution in a <code>Timeout</code>.</p>
<p>As an aside, it is interesting to note that the Decorator pattern is just the Object-Oriented equivalent of function composition in a functional language. Scala makes this especially explicit since everything is both an Object and a Function (it is a function if it is an object that responds to the method <code>#apply()</code>). A Decorator around an object that only implements <code>#apply()</code> is pure Function-composition as you would see in Haskell, ML, and so forth. I might phrase this as: <strong>function composition is a degenerate case of the Decorator pattern.</strong></p>
<p>The implementation of the <code>Timeout</code> function is shown for the curious. It uses threads and is weird but cool.</p>
<pre>    object Timeout {
      val timer = new Timer("Timer thread", true)

      def apply[T](timeout: Duration)(f: =&gt; T)(onTimeout: =&gt; Unit): T = {
        @volatile var cancelled = false
        val task = if (timeout.inMillis &gt; 0) Some(schedule(timeout, { cancelled = true; onTimeout })) else None
        try {
          f
        } finally {
          task map { t =&gt;
            t.cancel()
            timer.purge()
          }
          if (cancelled) throw new TimeoutException
        }
      }

      private def schedule(timeout: Duration, f: =&gt; Unit) = {
        val task = new TimerTask() {
          override def run() { f }
        }
        timer.schedule(task, timeout.inMillis)
        task
      }
    }</pre>
<p>(An alternative implementation of <code>Timeout</code> could use Futures, but that&#8217;s a subject for another blog post)</p>
<h3>Modularity and testing techniques</h3>
<p>One of the principal advantages of (or stated another way, one of the principal motivations for) writing Decorator-oriented code is how easy it is to write isolated unit tests of that code. To test the timeout functionality of the <code>TimingOutQuery</code> we don&#8217;t need to interact with a database at all. We can write behavioral/mockish tests like this:</p>
<pre>
    val latch = new CountDownLatch(1)
    val query = new FakeQuery(List(resultSet)) {
      override def cancel() = { latch.countDown() }

      override def select[A](f: ResultSet =&gt; A) = {
        latch.await(2.second.inMillis, TimeUnit.MILLISECONDS)
        super.select(f)
      }
    }
    val timingOutQuery = new TimingOutQuery(query, timeout)

    timingOutQuery.select { r =&gt; 1 } must throwA[SqlTimeoutException]
    latch.getCount mustEqual 0
</pre>
<p>If the timeout functionality was just inlined into the <code>#select()</code> method of the source code of the <code>Query</code> class, or &#8220;bolted on&#8221; as an <code>alias_method_chain</code> in Ruby (or added as &#8220;advice&#8221; in some AOP shit) you could not write this test without talking to the database and somehow finding a query that takes long enough that it will actually hit the timeout. Because we instead use Decorators, to test the code we can use a fake query that implements the <code>Query</code> interface but that doesn&#8217;t talk to the database at all. Here we use a <code>CountDownLatch</code> to &#8220;halt&#8221; execution for a bounded amount of time, thus triggering the timeout.</p>
<h3>Tying it together with Factories</h3>
<p>Back to our original mission. So now we have a way of layering on timeout functionality on top of a <code>Query</code> object. But how do we ensure that Timeouts get used when we want them to? The thing that glues this all together is to make sure that everybody that needs to instantiate a Query object never ever calls <code>new Query</code> directly. We provide instead a Factory as a parameter to the method that needs to manufacture the object. The programmer chooses which Factory to provide at runtime. Here is a Factory that makes <code>TimingOutQueries</code>:</p>
<pre>
    class TimingOutQueryFactory(queryFactory: QueryFactory, timeout: Duration) extends QueryFactory {
      def apply(connection: Connection, query: String, params: Any*) = {
        new TimingOutQuery(queryFactory(connection, query, params: _*), timeout)
      }
    }
</pre>
<p>Since <code>TimingOutQueries</code> are decorators around regular <code>Queries</code>, to manufacture a <code>TimingOutQuery</code> you have to first manufacture a regular <code>Query</code>. In this example, the <code>TimingOutQueryFactory</code> takes another Factory as an argument. This could be a simple <code>QueryFactory</code> or something more complex&#8211;allowing Factories to be composed indefinitely. With this we stack together timeouts, logging, statistics gathering, and debugging like so many pieces of legos. This smacks of the oft-ridiculed Java <code>AbstractFactoryFactoryInterface</code>. But let me put it bluntly: <code>AbstractFactoryFactoryInterface's</code> are how you write real, modular software&#8211;not little fart applications.</p>
<p>This seems like a bit of a mind-fuck because we here have Factory Decorators that take Decorated Factories that make Decorated Queries. It&#8217;s so meta! (Actually, &#8220;meta&#8221; in Greek means nothing like &#8220;meta&#8221; in English. &#8220;Meta&#8221; plus the accusative means &#8220;after&#8221; so Aristotle&#8217;s Metaphysics is actually just a book &#8220;after [the book on] physics&#8221;. Anyway.) So all these crazy <code>FactoryFactoryDecorators</code> sound kind-of scary at first but it is just the kind of abstraction on top of abstraction and closure under composition that allows complex software to be made simple. <strong>Manage complexity by taking many things and re-conceiving of them as just one thing; this one thing is then combined with many other things and the process is repeated up the ladder of abstraction until you reach the Godhead.</strong></p>
<h3>Taking this to the next level</h3>
<p>To take this even further, let&#8217;s add a new feature: per-query timeouts. At one point in the history of <code>FlockDB</code>, there was a global 3-second timeout. This was really stupid given that our most common query has a latency of 0.5ms and a standard deviation of 2ms. If you have a global timeout you must set your timeout around your most expensive query not your most common query (otherwise, your most expensive query will always timeout!). But for a production system, cheap frequent queries, if they start exceeding 2 standard deviations, can take down your site. So a sensible timeout for these frequent queries is like 5ms. But we had it set to 3,000 ms!! Yikes. So let&#8217;s change it!</p>
<pre>
    class PerQueryTimingOutQueryFactory(queryFactory: QueryFactory, timeouts: Map[String, Duration])
      extends QueryFactory {

      def apply(connection: Connection, query: String, params: Any*) = {
        new TimingOutQuery(queryFactory(connection, query, params: _*), timeouts(query)) // YAY
      }
    }
</pre>
<p>That&#8217;s it. We&#8217;ve now implemented a new <code>Timeout</code> strategy in one line of code! And to wire it all together it is a piece of cake! <code>Querulous</code> makes no assumptions about how best to implement a timing-out strategy, it doesn&#8217;t even assume you&#8217;ll want timeouts (in fact, there are some cases you don&#8217;t want any timeouts). <code>Querulous</code> achieves modularity by providing an &#8220;injection point&#8221; for the programmer to layer on custom functionality. It takes <code>QueryFactories</code> as a parameter to the method, which can return arbitrarily decorated <code>Queries</code>.</p>
<p>I love this example because it&#8217;s so simple but yet it&#8217;s no toy. It also emphasizes the value of Dependency Injection more generally than just with Factories. We could have written the <code>TimingOutQuery</code> with a static global constant (probably the most common programming technique):</p>
<pre>
    class TimingOutQuery(query: Query) extends QueryProxy(query) {
      val TIMEOUT = 3.seconds
</pre>
<p>But intead it is injected as a parameter to the constructor to the <code>TimingOutQuery</code>:</p>
<pre>
     class TimingOutQueryFactory(queryFactory: QueryFactory, timeout: Duration) extends QueryFactory {
        def apply(connection: Connection, query: String, params: Any*) = {
          new TimingOutQuery(queryFactory(connection, query, params: _*), timeout)
        }
      }
</pre>
<p>This enables the <code>TimingOutQueryFactory</code> to invoke a function to choose the appropriate timeout for this query. In this case, we just look some shit up in a hash table (<code>timeouts(query)</code>) and we&#8217;re done.</p>
<p>Yes, all this <code>FactoryFactory</code> bullshit is exactly what you hate about Java. But it&#8217;s amazing not how just short this code is but that it could be configured by any programmer anywhere, regardless of whether they have access to the source code that actually instantiates and executes queries. Any user of <code>Querulous</code> can decide if she want timeouts or not, and she can decide if they also want debugging, stats gathering, and so forth&#8211;<code>Querulous</code> hard-codes no assumptions. So, yay modularity.</p>
<h3>Postscript:</h3>
<p>Check out <a href="http://github.com/nkallen/querulous">Querulous</a>.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/magicscalingsprinkles.wordpress.com/487/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/magicscalingsprinkles.wordpress.com/487/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/magicscalingsprinkles.wordpress.com/487/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/magicscalingsprinkles.wordpress.com/487/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/magicscalingsprinkles.wordpress.com/487/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/magicscalingsprinkles.wordpress.com/487/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/magicscalingsprinkles.wordpress.com/487/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/magicscalingsprinkles.wordpress.com/487/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/magicscalingsprinkles.wordpress.com/487/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/magicscalingsprinkles.wordpress.com/487/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/magicscalingsprinkles.wordpress.com/487/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/magicscalingsprinkles.wordpress.com/487/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/magicscalingsprinkles.wordpress.com/487/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/magicscalingsprinkles.wordpress.com/487/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=magicscalingsprinkles.wordpress.com&amp;blog=5347219&amp;post=487&amp;subd=magicscalingsprinkles&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://magicscalingsprinkles.wordpress.com/2010/02/08/why-i-love-everything-you-hate-about-java/feed/</wfw:commentRss>
		<slash:comments>37</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/d9914cfbec64060f4053fc221a2a7536?s=96&#38;d=monsterid&#38;r=R" medium="image">
			<media:title type="html">nkallen</media:title>
		</media:content>
	</item>
		<item>
		<title>Why Arel?</title>
		<link>http://magicscalingsprinkles.wordpress.com/2010/01/28/why-i-wrote-arel/</link>
		<comments>http://magicscalingsprinkles.wordpress.com/2010/01/28/why-i-wrote-arel/#comments</comments>
		<pubDate>Thu, 28 Jan 2010 23:35:16 +0000</pubDate>
		<dc:creator>nkallen</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://magicscalingsprinkles.wordpress.com/?p=471</guid>
		<description><![CDATA[The upcoming version 3 of Ruby on Rails will feature a sexy new querying API from ActiveRecord. Here is an example: User.order('users.id DESC').limit(20).includes(:items) You can see that all queries are now chainable. This has two principal benefits: first, you can programmatically generate complex queries (based on user input or other data); and second, you can [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=magicscalingsprinkles.wordpress.com&amp;blog=5347219&amp;post=471&amp;subd=magicscalingsprinkles&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>The upcoming version 3 of Ruby on Rails will feature a sexy new querying API from ActiveRecord. Here is an <a href="http://m.onkey.org/2010/1/22/active-record-query-interface">example</a>:</p>
<p><code><br />
    User.order('users.id DESC').limit(20).includes(:items)<br />
</code></p>
<p>You can see that all queries are now chainable. This has two principal benefits: first, you can programmatically generate complex queries (based on user input or other data); and second, you can refactor your queries to eliminate code duplication in a way that you never could before.</p>
<p>The way that such chaining is possible is that each &#8220;query&#8221; (e.g., <code>Users.order(...)</code>) returns not an array of data, but a query object that one can manipulate still further. Only when you try to iterate through the data is a SQL query composed and then executed on the database.</p>
<p>If this sounds to you similar to &#8220;named_scope&#8221;, you&#8217;re spot on. After I wrote &#8220;named_scope&#8221; I immediately asked myself &#8220;but what if every query was a named_scope? What if named_scope were the rule and not the exception?&#8221;. I saw, unfortunately, that in order to do this I would need to re-write ActiveRecord.</p>
<p>So I set out to re-write ActiveRecord. I <a href="http://wiki.github.com/rails/rails/activerecord-refactoring">announced my intentions</a> (and then began a quixotic quest that would ultimately fail, then later succeed thanks to other people&#8217;s help).</p>
<p>I realized, though, that in order to re-write ActiveRecord, it would be best for the purposes of encapsulation to create a whole new self-contained query language; ideally, one that could underlie both DataMapper and ActiveRecord. So I began work on Arel, an Object-Oriented interpretation of the <a href="http://en.wikipedia.org/wiki/Relational_algebra">Relational Algebra</a>. The Relational Algebra is a mathematical model for representing &#8220;queries&#8221; on data. In many ways it resembles SQL (which is modeled on the algebra) but with slightly different jargon (&#8220;project&#8221; for &#8220;select&#8221;, &#8220;select&#8221; for &#8220;where&#8221;, etc.).</p>
<p>But the Relational Algebra differs greatly from SQL in that it has the property of <a href="http://en.wikipedia.org/wiki/Closure_(mathematics)">&#8220;closure&#8221; under composition</a>. That is, every operation on a relation (such as adding a &#8220;where&#8221; clause (aka &#8220;selection&#8221;)) returns a new relation where one can subsequently add more operations. SQL distinguishes queries from result sets: and so queries cannot be composed since queries are just strings (e.g., <code>SELECT * FROM foo</code>). To manipulate a SQL query we must manipulate a string. There is a string algebra, but its operations are things like substring, concatenation, substitution, and so forth&#8211;not so useful. In the Relational Algebra, there are no queries per se; everything is either a relation or an operation on a relation. Connect the dots and with the algebra we get something like &#8220;everything is named_scope&#8221; for free.</p>
<p>Ever since I read the book <a href="http://mitpress.mit.edu/sicp/">Structure and Interpretation of Computer Programs</a> I have been fascinated by the concept of closure under composition. (If you haven&#8217;t read this book, you must; it&#8217;s like Euclid&#8217;s Elements). There is <a href="http://mitpress.mit.edu/sicp/full-text/book/book-Z-H-15.html#%_sec_2.2.4">a chapter on a Picture Language</a> that represents transformations on pictures; each transformation generates a picture that can be further transformed:</p>
<p><code><br />
    (define wave2 (beside wave (flip-vert wave)))<br />
</code></p>
<div class="wp-caption alignnone" style="width: 199px"><img alt="" src="http://mitpress.mit.edu/sicp/full-text/book/ch2-Z-G-34.gif" title="The picture is ugly but the code is beautiful" width="189" height="188" /><p class="wp-caption-text">The picture is ugly but the code is beautiful</p></div>
<p>In other words, the picture language has closure under composition. To this day, when I work in completely different languages and on somewhat different problems I&#8217;m fascinated by the same concept of closure. <a href="http://gist.github.com/288511">This gist </a> which I will someday re-write into a blog-post illustrates how I often use the Decorator pattern with Factories and Dependency Injection to structure programs. This is closure writ-large, and is a different way to think about the architecture of your software than the usual &#8220;Domain Driven&#8221;/Ontological approach. (Actually, it has much in common with the &#8220;Test Driven&#8221; approach).</p>
<p>Anyway. Just before I began working on Arel I learned of <a href="http://www.sqlalchemy.org/">SqlAlchemy</a>. SqlAlchemy was inspiring, but it was written in Python (and thus useless for RoR) and also had a couple design decisions that I thought were fundamentally (not superficially) wrong. I intended to do something radical, something SQL Alchemy couldn&#8217;t do: a pure relational algebra with closure under composition even in the presence of aggregations. To explain my motivations though, I want to illustrate two &#8220;beautiful&#8221; querying problems; one is solved well in SQL, the other not. The first is the technique to do <a href="http://dev.mysql.com/doc/refman/5.0/en/example-maximum-column-group-row.html">a group-wise maximum of a certain column</a>. In this example, we try to find the most expensive dealer of a given article. for all articles:</p>
<p><code><br />
    SELECT s1.article, s1.dealer, s1.price<br />
    FROM shop s1<br />
    LEFT JOIN shop s2 ON s1.article = s2.article AND s1.price &lt; s2.price<br />
    WHERE s2.article IS NULL;<br />
</code></p>
<p>This, to me, is one of the great mind-blowing SQL queries. It means something like &quot;find the dealer for which there exists no dealer selling the same product at a lesser price&quot;. It is the &#8220;double negative&#8221; restatement of &#8220;most expensive&#8221;. In other words, &#8220;not the lesser expensive&#8221;. It&#8217;s this kind of radical restatement of problems that I hope to accomplish with my work. Of course this actually has nothing to do with Arel, although it&#39;s expressible trivially in Arel. But it provides some insight into my thinking about why I write software and why I am concerned so much about how software is written.</p>
<p>The other query I am fascinated by is the following. Suppose we have a users table and a photos table and we want to select all user data and a *count* of the photos they have created. In SQL, it is expressed like thus:</p>
<p><code><br />
    SELECT users.*, photos_aggregation.cnt<br />
    FROM users<br />
    LEFT OUTER JOIN (SELECT user_id, count(*) as cnt FROM photos GROUP BY user_id) AS photos_aggregation<br />
      ON photos_aggregation.user_id = users.id<br />
</code></p>
<p>You&#39;ll note the use of the derived table in the subselect. This is terrible, in my opinion. Only advanced SQL programmers know how to write this (I&#8217;ve often asked this question in job interviews I&#8217;ve never once seen anybody get it right). And it shouldn&#8217;t be hard! It&#8217;s just what happens when you lack closure under composition. I was determined to be able to write code like the following:</p>
<p><code><br />
    photo_counts = photos.<br />
      group(photos[:user_id]).<br />
      project(photos[:user_id], photos[:id].count)<br />
</code></p>
<p>And finally,</p>
<p><code><br />
    users.join(photo_counts).on(users[:id].eq(photo_counts[:user_id]))<br />
</code></p>
<p>If this seems simple to you, you are as naive as I was when I first started working on Arel. It is anything but simple: Arel needs to recognize when you are joining with relations that are aggregations (i.e., have a &quot;group by&quot;) and produce a derived table (a subselect with a unique name) and then join with that. Since we have closure under composition, no matter how many joins and how many aggregations you have, Arel needs to generate unique derived tables and scope all attribute names to them. Since derived tables can be nested infinitely the implementation of this is incredibly tricky; one of the hardest problems I&#39;ve ever solved, and I&#39;m pretty happy how it all turned out.</p>
<p>But therein lies the rub. All of my open-sourced projects share two attributes. First, the source code is extremely stylized and meant to be /read/ more than /used/. They are literary arguments in code much more than a useful piece of infrastructure. If you read the source-code to Arel you will see a highly affected &quot;combinator&quot; and &quot;interpreter&quot; style of coding. </p>
<p>If you look at <a href="http://github.com/nkallen/screw-unit">Screw.Unit </a>, for example, not only is it an argument about how tests should be written but it is probably the most unusual Javascript code you will ever see; it is written in a &#8220;concrete&#8221; style inspired by Self&#8217;s Morphic.</p>
<p>Similarly, Arel is a two-fold argument: this is how you should interact with a database, and this is how software can be written to affect a unique personal style.</p>
<p>The second attribute of all my open-source projects is that I release them and neglect them. This makes me a terrible steward of open-source software. But my aim is to introduce ideas into the world more so than to keep infrastructure alive. (My upcoming open-source project, FlockDB (a distributed graph database) will hopefully be different; we hope to run Twitter off of the open version indefinitely.)</p>
<p>And this explains why I &#8220;finished&#8221; Arel in May of 2008 but only now has it been integrated into Rails. If it were not for the heroic integration work of Emilio Tagua, the leadership of Bryan Helmkamp, and the support of DHH and Michael Koziarsky, Arel would be but an idea.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/magicscalingsprinkles.wordpress.com/471/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/magicscalingsprinkles.wordpress.com/471/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/magicscalingsprinkles.wordpress.com/471/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/magicscalingsprinkles.wordpress.com/471/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/magicscalingsprinkles.wordpress.com/471/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/magicscalingsprinkles.wordpress.com/471/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/magicscalingsprinkles.wordpress.com/471/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/magicscalingsprinkles.wordpress.com/471/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/magicscalingsprinkles.wordpress.com/471/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/magicscalingsprinkles.wordpress.com/471/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/magicscalingsprinkles.wordpress.com/471/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/magicscalingsprinkles.wordpress.com/471/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/magicscalingsprinkles.wordpress.com/471/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/magicscalingsprinkles.wordpress.com/471/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=magicscalingsprinkles.wordpress.com&amp;blog=5347219&amp;post=471&amp;subd=magicscalingsprinkles&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://magicscalingsprinkles.wordpress.com/2010/01/28/why-i-wrote-arel/feed/</wfw:commentRss>
		<slash:comments>25</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/d9914cfbec64060f4053fc221a2a7536?s=96&#38;d=monsterid&#38;r=R" medium="image">
			<media:title type="html">nkallen</media:title>
		</media:content>

		<media:content url="http://mitpress.mit.edu/sicp/full-text/book/ch2-Z-G-34.gif" medium="image">
			<media:title type="html">The picture is ugly but the code is beautiful</media:title>
		</media:content>
	</item>
		<item>
		<title>The Meaning of Information Technology</title>
		<link>http://magicscalingsprinkles.wordpress.com/2009/11/02/the-meaning-of-information-technology/</link>
		<comments>http://magicscalingsprinkles.wordpress.com/2009/11/02/the-meaning-of-information-technology/#comments</comments>
		<pubDate>Mon, 02 Nov 2009 02:00:05 +0000</pubDate>
		<dc:creator>nkallen</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://magicscalingsprinkles.wordpress.com/?p=48</guid>
		<description><![CDATA[The first commercial computer was the Lyons Electronic Office I and was used in 1951 to perform vast calculations pertaining to the fabrication and consumption of biscuits. You see, after the war, J. Lyons &#38; Co., a popular chain of British tea shops, was confronted with an appetite for pastries so astronomical (which is understandable [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=magicscalingsprinkles.wordpress.com&amp;blog=5347219&amp;post=48&amp;subd=magicscalingsprinkles&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>The first commercial computer was the <a href="http://en.wikipedia.org/wiki/LEO_I">Lyons Electronic Office I</a> and was used in 1951 to perform vast calculations pertaining to the fabrication and consumption of biscuits. You see, after the war, <a href="http://en.wikipedia.org/wiki/J._Lyons_and_Co.">J. Lyons &amp; Co.</a>, a popular chain of British tea shops, was confronted with an appetite for pastries so astronomical (which is understandable given years of tedious disputes with Germany), that the human mind was incapable of solving unaided the problem of distributing tea cakes to their customers.</p>
<p>Hidden in this story is the true meaning of all information technology.</p>
<p><strong>A brief statement of the problem.</strong></p>
<p>There is an old logical puzzle called the <a href="http://plato.stanford.edu/entries/sorites-paradox/">Sorites Paradox</a>, first articulated by the Megarian logician Eubulides of Miletus. It predates the stored program computer by 2,000 years but it similarly concerns the production of pastries:</p>
<blockquote><p>Would you describe a single grain of wheat as a heap? No. Would you describe two grains of wheat as a heap? No&#8230;. You must admit the presence of a heap sooner or later, so where do you draw the line?
</p></blockquote>
<p>This problem was of keen interest to the philosophical community for thousands of years, principally because the Greek recipe for tea cakes called for two heaping tablespoons of sugar. Some philosophers went so far as to vow to grow a beard and engage in pederasty until a solution to the problem was found. But all efforts were in vain; the problem remains unsolved to this day.</p>
<p>Unfortunately, the problem has only become ever more acute in the modern era. In fact, far from <em>only</em> destabilizing the fabrication of pastries, it has further undermined every area of society. Consider the process of voting. If no one voted, one vote would affect the outcome. But if millions of people vote, one vote makes little difference.</p>
<p>In fact, the defining characteristic of the modern era is that every aspect of society is heaping. To understand how this came to be, we must revisit ancient history.</p>
<p><strong>Some scientifical facts.</strong></p>
<p>During the pre-historic era, when mankind lived in trees and swam in lagoons, we lived in small clans and tribes of dozens up to a few hundred people. During this long honeymoon period in homo sapiens history, we evolved our cognitive abilities through careful grooming and diligent fornicating. The brain developed the ability to speak languages and sympathize with other people and feel jealousy and kindness and all that other stuff. In other words, we evolved a social technology that equipped us for living in society and dealing with the ordeals caused by other people.</p>
<p>But that social technology is ill-equipped to deal with the humongous heaps of the modern world. We meet hundreds of people every year and can&#8217;t remember any of their names. We evolved language and vocal chords to cover long distances but somebody put skyscrapers in the way and anyway we now live like <em>really</em> long distances away, like you have to fly an airplane to see them or at least ride a bicycle. And then there are these celebrity neanderthals like Ashton Kutcher who are adored for their plumage by a multitude who greedily read every banal detail of his private life in magazines like Star that ship millions of copies to every end of a giant sphere whose radius is 6,378.1 kilometers; or on a Twitter that delivers every inane thing he tweets to 4 million people, 10 times daily. It goes without saying that this would not be possible if not for a defect in our programming in the face of the massive scale of the world.</p>
<p><strong>Everything has become a giant fucking heap.</strong></p>
<p>The modern world is profoundly inhumane. Mankind is incapable of reasoning about the heaping constructs of mass culture using the technes of intimacy that are an hundred thousand years old. For example, we need to be constantly reassured that celebrities are just like us. They eat waffles and pick up dry cleaning. If we do not share this understanding of Ashton Kutcher, we become overwhelmed by existential anomie and commit suicide.</p>
<p>Human beings need to understand one another in terms of primordial intimacies because man has no other tools for understanding the solicitations of man. But if the size of the world no is on longer amenable to intimacy technologies, then mankind must invent information technologies that rehumanize the world.</p>
<p>Thus the proliferation of social software on the web. The reification of the social graph in Friendster; the Facebook Newsfeed and the Twitter; and the Foursquare all serve this one purpose: to rehumanize an inhumane world. Let&#8217;s consider each of these technologies one at a time.</p>
<ol>
<li>Friendster&#8217;s reification of the social graph makes it possible to understand the ties that bind us all together when we only have room in our brains for the intrigues of a few dozen relationships.</li>
<li>The Facebook Newsfeed and the Twitter make it possible to share in the thoughts and intimate moments of those who inhabit different neighborhoods, and different schools, and different jobs, and make different choices than us from amongst the vast cornucopia of mass-produced art sold to us by the culture industry. Finally,</li>
<li>the Foursquare coordinates the alienated existence of cosmopolitan voluptuaries into a shared bacchanal.</li>
</ol>
<p><strong>Technology and self-criticism.</strong></p>
<p>I cannot help but be a technological optimist because technology is mankind&#8217;s only bulwark against the barbarism of heaps. But I&#8217;ll grant that technology is imperfect; it is sometimes fair to criticize the <a href="http://www.amazon.com/Tyranny-E-mail-Four-Thousand-Year-Journey-Inbox/dp/1416576738">Tyranny of Technology</a>. The usual argument goes that all these tweets and text messages and notifications that &#8220;a software update is available&#8221; leave no space quiet, provide no room for contemplation. It is true: we do live in a world of interruptions; interruptions created by information technology. But we should not be surprised by this fact and no more should we despair of it. One generation of technology solves the problems of the previous but causes problems of its own. The next generation of technology repeats this story; a story as old as mankind itself. This is the dialectics of history.</p>
<p>Do not doubt, then, that a technology will arise to solve this problem too. We, the makers, shall fabricate a machine to produce quiet and contemplation. In fact, at this very moment, I have a patent pending on a pair of contemplation goggles. And in just a few weeks I will release a beta of a contemplation-inducing goggular Twitter client. I&#8217;m sure it will be received to massive acclaim and to the profound benefit of humanity.</p>
<p>So! Old men: do not fear for the future. We young people, we hackers and makers, we have it all under control. We know the true meaning of information technology. We shall save us all from the giant fucking heaps.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/magicscalingsprinkles.wordpress.com/48/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/magicscalingsprinkles.wordpress.com/48/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/magicscalingsprinkles.wordpress.com/48/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/magicscalingsprinkles.wordpress.com/48/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/magicscalingsprinkles.wordpress.com/48/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/magicscalingsprinkles.wordpress.com/48/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/magicscalingsprinkles.wordpress.com/48/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/magicscalingsprinkles.wordpress.com/48/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/magicscalingsprinkles.wordpress.com/48/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/magicscalingsprinkles.wordpress.com/48/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/magicscalingsprinkles.wordpress.com/48/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/magicscalingsprinkles.wordpress.com/48/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/magicscalingsprinkles.wordpress.com/48/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/magicscalingsprinkles.wordpress.com/48/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=magicscalingsprinkles.wordpress.com&amp;blog=5347219&amp;post=48&amp;subd=magicscalingsprinkles&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://magicscalingsprinkles.wordpress.com/2009/11/02/the-meaning-of-information-technology/feed/</wfw:commentRss>
		<slash:comments>10</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/d9914cfbec64060f4053fc221a2a7536?s=96&#38;d=monsterid&#38;r=R" medium="image">
			<media:title type="html">nkallen</media:title>
		</media:content>
	</item>
		<item>
		<title>Introducing Cache Money</title>
		<link>http://magicscalingsprinkles.wordpress.com/2008/12/11/introducing-cache-money/</link>
		<comments>http://magicscalingsprinkles.wordpress.com/2008/12/11/introducing-cache-money/#comments</comments>
		<pubDate>Thu, 11 Dec 2008 06:25:46 +0000</pubDate>
		<dc:creator>nkallen</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://magicscalingsprinkles.wordpress.com/?p=17</guid>
		<description><![CDATA[Pre-requisite: please read my article on Write-through caching to understand why this is useful. Most caching solutions in the Rails world involve something like Cache-Fu: an alternative API to ActiveRecord that explicitly annotates all call sites with cache rules. User.find(1) becomes User.get_cache(1) User.find(:all, ...) becomes User.get_cache("query_name", :ttl =&#62; 5.minutes) { User.find(:all, ... )} I hate [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=magicscalingsprinkles.wordpress.com&amp;blog=5347219&amp;post=17&amp;subd=magicscalingsprinkles&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<blockquote><p>Pre-requisite: please read my article on <a href="http://magicscalingsprinkles.wordpress.com/2008/11/24/write-through-cacheing-is-an-essential-part-of-a-healthy-scaling-strategy/">Write-through caching</a> to understand why this is useful.</p></blockquote>
<p>Most caching solutions in the Rails world involve something like Cache-Fu: an alternative API to ActiveRecord that explicitly annotates all call sites with cache rules.</p>
<ul>
<li><code>User.find(1)</code> becomes <code>User.get_cache(1)</code></li>
<li><code>User.find(:all, ...)</code> becomes <code>User.get_cache("query_name", :ttl =&gt; 5.minutes) { User.find(:all, ... )}</code></li>
</ul>
<p>I hate this kind of interface, which places the burden on the caller and meekly surrenders any attempt at encapsulation. Your codebase will be littered with haphazard cache rules in your controllers, views, and models.</p>
<p>But even worse are the explicit cache expiry rules. As you cache non-trivial queries, you&#8217;ll have to find all the of the writes in your system that could possibly invalidate the results of the query. It&#8217;s a tedious and onerous effort: after hundreds of hours of debugging you&#8217;ll finally get <code>expire_cache</code> in just the right places.</p>
<p>A solution to this brittle, messy coding style is now available, and ready for production use. <a href="http://github.com/nkallen/cache-money/tree/master">`Cache Money`</a> is a plugin for ActiveRecord that <strong>transparently</strong> provides <a href="http://en.wikipedia.org/wiki/Cache"><i>write-through</i> and <i>read-through</i> caching</a> functionality using Memcached. With <a href="http://github.com/nkallen/cache-money/tree/master">`Cache Money`</a>, queries are <strong>automatically cached</strong> for you; and similarly, <strong>cache expiry happens automatically</strong> as <code>after_save</code> and <code>after_destroy</code> events.</p>
<p>This doesn&#8217;t just apply to trivial queries. Very complex, sophisticated queries are handled effortlessly; the vast majority of ActiveRecord usage is transparently materialized, indexed, and kept fresh in Memcached. Here are some examples:</p>
<ul>
<li><code>User.find(1)</code></li>
<li><code>User.find(:all, :conditions =&gt; { :screen_name =&gt; 'bob' })</code></li>
<li><code>Friendship.find(:all, :conditions =&gt; ['friendships.creator_id = ? AND friendships.receiver_id = ?', ...])</code></li>
<li><code>users.direct_messages</code></li>
<li><code>users.direct_messages.find(1)</code></li>
<li><code>users.direct_messages.count</code></li>
<li><code>User.find(:all, :limit =&gt; 10, <img src='http://s1.wp.com/wp-includes/images/smilies/icon_surprised.gif' alt=':o' class='wp-smiley' /> rder =&gt; 'id DESC')</code></li>
</ul>
<p>All of these, and much more will automatically be cached and kept fresh as you write to the database. <a href="http://magicscalingsprinkles.wordpress.com/2008/11/24/write-through-cacheing-is-an-essential-part-of-a-healthy-scaling-strategy/">This greatly lessens the load on your database and makes your site impervious to catastrophic replication lag</a>.</p>
<p>The way <a href="http://github.com/nkallen/cache-money/tree/master">`Cache Money`</a> works is by materializing the equivalent of database indices in Memcached. It&#8217;s as if you store your indices in a distributed hash table instead of an in-process BTree. Just as with a database, you declare your indices:</p>
<p><code><br />
    class User &lt; ActiveRecord::Base<br />
      index :screen_name<br />
    end</p>
<p>    class Friendship<br />
      index [:creator_id, :receiver_id]<br />
    end</p>
<p>    class DirectMessage<br />
      index :user_id<br />
      index [:user_id, :id]<br />
    end<br />
</code></p>
<p>There are lots of configurable options like TTLs:<br />
<code><br />
    index :user_id, :ttl =&gt; 1.day<br />
</code></p>
<p>You can also specify limits to ensure that your indices do not grow too large:<br />
<code><br />
    index :user_id, :limit =&gt; 500, :buffer =&gt; 20<br />
</code></p>
<p>(This keeps a rolling window of 500 items. The <code>buffer</code> option indicates how many &#8220;extra&#8221; you want to keep around in case of deletes in order to maintain at least 500 items. If more than 20 are deleted, the index will be repopulated to ensure there are at least 500 items in it). </p>
<p>This is just the tip of the iceberg. Many advanced utilities are included for even more sophisticated use, including <strong>shared locks</strong> to deal with distributed computations on shared memory, <strong>simulated transactions in Memcached</strong> (which obviates the need for locks in most cases), high-performance <strong>mocks for your tests</strong>, and in process-caches to minimize network operations during a single request-response cycle.</p>
<p>A version of this code is in production use at Twitter and is one part of the reason Twitter&#8217;s uptime has improved so much over the last several months. This is real, pragmatic, unmagical, production-ready code that can be a big part of your Rails scaling strategy. It is designed with massive datasets and real-world operational challenges in mind. And it&#8217;s almost effortless to use, since it requires no changes to how you use ActiveRecord.</p>
<p><a href="http://github.com/nkallen/cache-money/tree/master">Check out `Cache Money` on github.</a></p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/magicscalingsprinkles.wordpress.com/17/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/magicscalingsprinkles.wordpress.com/17/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/magicscalingsprinkles.wordpress.com/17/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/magicscalingsprinkles.wordpress.com/17/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/magicscalingsprinkles.wordpress.com/17/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/magicscalingsprinkles.wordpress.com/17/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/magicscalingsprinkles.wordpress.com/17/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/magicscalingsprinkles.wordpress.com/17/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/magicscalingsprinkles.wordpress.com/17/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/magicscalingsprinkles.wordpress.com/17/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/magicscalingsprinkles.wordpress.com/17/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/magicscalingsprinkles.wordpress.com/17/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/magicscalingsprinkles.wordpress.com/17/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/magicscalingsprinkles.wordpress.com/17/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=magicscalingsprinkles.wordpress.com&amp;blog=5347219&amp;post=17&amp;subd=magicscalingsprinkles&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://magicscalingsprinkles.wordpress.com/2008/12/11/introducing-cache-money/feed/</wfw:commentRss>
		<slash:comments>29</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/d9914cfbec64060f4053fc221a2a7536?s=96&#38;d=monsterid&#38;r=R" medium="image">
			<media:title type="html">nkallen</media:title>
		</media:content>
	</item>
		<item>
		<title>Write-Through Cacheing is an Essential Part of a Healthy Scaling Strategy</title>
		<link>http://magicscalingsprinkles.wordpress.com/2008/11/24/write-through-cacheing-is-an-essential-part-of-a-healthy-scaling-strategy/</link>
		<comments>http://magicscalingsprinkles.wordpress.com/2008/11/24/write-through-cacheing-is-an-essential-part-of-a-healthy-scaling-strategy/#comments</comments>
		<pubDate>Mon, 24 Nov 2008 07:05:20 +0000</pubDate>
		<dc:creator>nkallen</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://magicscalingsprinkles.wordpress.com/?p=8</guid>
		<description><![CDATA[The debate around &#8220;Does Rails scale?&#8221; I&#8217;ll leave to the armchair architects. But one thing I know is that having one 100% Beef Database doesn&#8217;t scale. With replication you can scale your database. With Master-Slave replication, you can have any number of read-slaves for one master; you perform reads (SELECT queries) on the slaves and [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=magicscalingsprinkles.wordpress.com&amp;blog=5347219&amp;post=8&amp;subd=magicscalingsprinkles&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>The debate around &#8220;Does Rails scale?&#8221; I&#8217;ll leave to the armchair architects. But one thing I know is that having one 100% Beef Database doesn&#8217;t scale.</p>
<p>With replication you can scale your database. With <a href="http://en.wikipedia.org/wiki/Master_slave">Master-Slave</a> <a href="http://en.wikipedia.org/wiki/Database_replication">replication</a>, you can have any number of read-slaves for one master; you perform reads (SELECT queries) on the slaves and issue writes (INSERT/UPDATE/DELETEs) on the master. With this strategy your write capacity wont scale but your read capacity can scale almost indefinitely. And anyway, since write and read actions have different performance characteristics, you&#8217;ll get the most out of your beefy machines if you&#8217;re into this role-play. By the way, the best Rails plugin for this is <a href="http://github.com/technoweenie/masochism/tree/master">masochism</a>.</p>
<h2> Replication Lag </h2>
<p>Still, Replication has its problems. The latency of information propagation from the master to the slave (and from slave to slave if you have a <a href="http://en.wikipedia.org/wiki/Tree_topology#Tree">tree topology</a>) can lead to data inconsistency.</p>
<p>Consider a user who creates a new account on your web site. A new record is INSERTed into the `users` table on the master database. On the next page load their record SELECTed from a random slave. But the information might not yet be propagated to the database slave! So the user gets an HTTP 500 error.</p>
<p>Typically, it takes only a fraction of a second for information to propagate. But it isn&#8217;t unusual to measure replication lag in seconds, minutes, or hours because of bugs in mysql, partial outages, and expensive queries. This is an every-day occurrence and you must plan accordingly.</p>
<p>Fortunately there is a solution, and it is <a>write-through</a> caching. At the same time as writing to the master database, write &#8220;through&#8221; a cache layer such as <a href="http://www.danga.com/memcached/">memcached</a>. If for all reads you first try to read from cache, you will always find data: data that hasn&#8217;t yet propagated from database to database is newest and therefore most likely to be in the cache.</p>
<p>Easier said, harder done. You&#8217;ll have smear your code with cream-cheese to get this to work. Unless there were some magical plugin that solved this problem for you&#8230;</p>
<h2> Testing for Replication Lag-induced defects </h2>
<p>But you can only obtain code cream cheese if you can even figure out what part of the site needs cacheing. You&#8217;d be crazy to test, live in production, bugs caused by non-deterministic replication lag. So you need to simulate replication lag somehow.</p>
<p>One technique that is almost foolproof is to use a comprehensive <a href="http://selenium.seleniumhq.org/index.html">Selenium</a> test-suite. Create a new Rails environment with your master and slave as two local databases. Load your fixtures into both databases. Don&#8217;t establish any replication relationship between the two databases &#8212; voila! you&#8217;ve just simulated infinite replication lag. Now run your Selenium suite. I&#8217;m sure it won&#8217;t be pretty, 500s upon 500s, but that&#8217;s what will happen to your users unless you implement write-through cacheing.</p>
<h2> Other Scaling Strategies </h2>
<p>Now, there are other database scaling strategies than master-slave replication. Master-Master replication can skirt replication lag if you use sticky sessions. But MySQL support for master-master replication is arguably not production-ready, and in any case such replication, especially combined with sticky sessions, has worse <a href="http://en.wikipedia.org/wiki/Fault-tolerant_system">failure characteristics</a> than master-slave.</p>
<p>The unicorn strategy of &#8220;sharding&#8221;/<a href="http://en.wikipedia.org/wiki/Partition_(database)">Database partitioning</a> does not obviate replication strategies; usually each partition has replication strategies if only for fault tolerance.</p>
<p>My fantasy scaling strategy involves skipping the database altogether. Rather than synchronously write to a database, write to a <a href="http://en.wikipedia.org/wiki/Message_queue">message queue</a>. Have a daemon read from the queue and write to your (partitioned) (replicated) database at its leisure. In the event of a write-database failure, the daemon gets backed up but there is no downtime since your site is completely decoupled from the write database. If you&#8217;re not concerned with in-order delivery, message queues scale effortlessly. (Please in no way consider this an endorsement of either ActiveMQ or RabbitMQ). In any case, writing to the database asynchronously from a daemon is only possible with sufficient write-through cacheing.</p>
<p>This is why I say write-through cacheing is critical to scaling. And in the next few weeks I&#8217;ll bring forth some code that shows how to do it right.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/magicscalingsprinkles.wordpress.com/8/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/magicscalingsprinkles.wordpress.com/8/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/magicscalingsprinkles.wordpress.com/8/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/magicscalingsprinkles.wordpress.com/8/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/magicscalingsprinkles.wordpress.com/8/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/magicscalingsprinkles.wordpress.com/8/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/magicscalingsprinkles.wordpress.com/8/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/magicscalingsprinkles.wordpress.com/8/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/magicscalingsprinkles.wordpress.com/8/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/magicscalingsprinkles.wordpress.com/8/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/magicscalingsprinkles.wordpress.com/8/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/magicscalingsprinkles.wordpress.com/8/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/magicscalingsprinkles.wordpress.com/8/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/magicscalingsprinkles.wordpress.com/8/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=magicscalingsprinkles.wordpress.com&amp;blog=5347219&amp;post=8&amp;subd=magicscalingsprinkles&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://magicscalingsprinkles.wordpress.com/2008/11/24/write-through-cacheing-is-an-essential-part-of-a-healthy-scaling-strategy/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/d9914cfbec64060f4053fc221a2a7536?s=96&#38;d=monsterid&#38;r=R" medium="image">
			<media:title type="html">nkallen</media:title>
		</media:content>
	</item>
		<item>
		<title>Initial Post</title>
		<link>http://magicscalingsprinkles.wordpress.com/2008/10/30/initial-post/</link>
		<comments>http://magicscalingsprinkles.wordpress.com/2008/10/30/initial-post/#comments</comments>
		<pubDate>Thu, 30 Oct 2008 05:26:34 +0000</pubDate>
		<dc:creator>nkallen</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://magicscalingsprinkles.wordpress.com/?p=3</guid>
		<description><![CDATA[I&#8217;ve decided to begin blogging again because I am working through a set of engineering problems that I need to think through as much as engineer through.  Since I&#8217;ve left Pivotal and joined Twitter, I&#8217;ve been working on a new class of problems, principally: architecture, scaling, and large-scale deployment. I spend as much time thinking [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=magicscalingsprinkles.wordpress.com&amp;blog=5347219&amp;post=3&amp;subd=magicscalingsprinkles&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve decided to begin blogging again because I am working through a set of engineering problems that I need to <em>think through </em>as much as <em>engineer through.</em> </p>
<p>Since I&#8217;ve left Pivotal and joined Twitter, I&#8217;ve been working on a new class of problems, principally: architecture, scaling, and large-scale deployment. I spend as much time thinking about how to<strong> safely deploy</strong> new functionality as building it. I program as much in system<strong> languages like C</strong> as in Ruby. I spend half of my time doing science: interpreting profiling data, logs,<strong> taking measurements,</strong> and performing statistical analysis.</p>
<p>I&#8217;m learning so much that my understanding of Software Engineering is completely changing. I love what I&#8217;m doing, what I&#8217;m learning, and I hope with this blog to share some of that enthusiasm as well as the few lessons I will learn and the many mistakes I will make.</p>
<p>The kinds of things I expect to write about are things like caching strategies, bottleneck analysis, fault tolerance, service-oriented architecture, deployment techniques, iterative development, simplicity, and beauty. Anyway, I hope you all enjoy it.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/magicscalingsprinkles.wordpress.com/3/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/magicscalingsprinkles.wordpress.com/3/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/magicscalingsprinkles.wordpress.com/3/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/magicscalingsprinkles.wordpress.com/3/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/magicscalingsprinkles.wordpress.com/3/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/magicscalingsprinkles.wordpress.com/3/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/magicscalingsprinkles.wordpress.com/3/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/magicscalingsprinkles.wordpress.com/3/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/magicscalingsprinkles.wordpress.com/3/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/magicscalingsprinkles.wordpress.com/3/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/magicscalingsprinkles.wordpress.com/3/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/magicscalingsprinkles.wordpress.com/3/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/magicscalingsprinkles.wordpress.com/3/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/magicscalingsprinkles.wordpress.com/3/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=magicscalingsprinkles.wordpress.com&amp;blog=5347219&amp;post=3&amp;subd=magicscalingsprinkles&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://magicscalingsprinkles.wordpress.com/2008/10/30/initial-post/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/d9914cfbec64060f4053fc221a2a7536?s=96&#38;d=monsterid&#38;r=R" medium="image">
			<media:title type="html">nkallen</media:title>
		</media:content>
	</item>
	</channel>
</rss>
