<?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/"
	>

<channel>
	<title>Brain Matters &#187; rails</title>
	<atom:link href="http://blog.agoragames.com/tag/rails/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.agoragames.com</link>
	<description></description>
	<lastBuildDate>Thu, 29 Jul 2010 19:13:58 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Rails 3.0.0.rc changes</title>
		<link>http://blog.agoragames.com/2010/07/27/rails-3-0-0-rc-changes/</link>
		<comments>http://blog.agoragames.com/2010/07/27/rails-3-0-0-rc-changes/#comments</comments>
		<pubDate>Tue, 27 Jul 2010 16:46:44 +0000</pubDate>
		<dc:creator>David Czarnecki</dc:creator>
				<category><![CDATA[Bending Rails]]></category>
		<category><![CDATA[Engineering]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[rails 3]]></category>
		<category><![CDATA[rails3.0.0.rc]]></category>

		<guid isPermaLink="false">http://blog.agoragames.com/?p=638</guid>
		<description><![CDATA[Rails 3.0.0 now has a release candidate. These are the changes I made to a new application I am working on to clear up any deprecation warnings.

Gemfile
gem &#8216;rails&#8217;, &#8216;3.0.0.rc&#8217;
gem &#8216;haml&#8217;, &#8216;3.0.14&#8242;
Obviously you have to tell your application to use the 3.0.0.rc. Also, it seems as if haml 3.0.13, which we were previously using, had some [...]]]></description>
			<content:encoded><![CDATA[<p>Rails 3.0.0 now has a <a href="http://weblog.rubyonrails.org/2010/7/26/rails-3-0-release-candidate">release candidate</a>. These are the changes I made to a new application I am working on to clear up any deprecation warnings.</p>
<p><span id="more-638"></span></p>
<p><strong>Gemfile</strong></p>
<p>gem &#8216;rails&#8217;, &#8216;3.0.0.rc&#8217;<br />
gem &#8216;haml&#8217;, &#8216;3.0.14&#8242;</p>
<p>Obviously you have to tell your application to use the 3.0.0.rc. Also, it seems as if haml 3.0.13, which we were previously using, had some incompatible changes with Rails 3.0.0.rc</p>
<p><strong>Rakefile</strong></p>
<p>Change:</p>
<p>Rails::Application.load_tasks</p>
<p>to:</p>
<p>YourApplicationName::Application.load_tasks</p>
<p><strong>config/environments/test.rb</strong></p>
<p>Add:</p>
<p>config.active_support.deprecation = :stderr</p>
<p><strong>config/routes.rb</strong></p>
<p>Change:</p>
<p>YourApplicationName::Application.routes.draw do |map|</p>
<p>to:</p>
<p>YourApplicationName::Application.routes.draw do</p>
<p>Rails 3 routing in great detail: <a href="http://www.engineyard.com/blog/2010/the-lowdown-on-routes-in-rails-3/">The Lowdown on Routes in Rails 3</a>.</p>




	<a rel="nofollow"  target="_blank" href="http://reddit.com/submit?url=http%3A%2F%2Fblog.agoragames.com%2F2010%2F07%2F27%2Frails-3-0-0-rc-changes%2F&amp;title=Rails%203.0.0.rc%20changes" title="Reddit"><img src="http://blog.agoragames.com/wp-content/plugins/var/www/waxer-blog/shared/wp-content/plugins/sociable/images/reddit.png" title="Reddit" alt="Reddit" class="sociable-hovers" /></a>
	<a rel="nofollow"  target="_blank" href="http://digg.com/submit?phase=2&amp;url=http%3A%2F%2Fblog.agoragames.com%2F2010%2F07%2F27%2Frails-3-0-0-rc-changes%2F&amp;title=Rails%203.0.0.rc%20changes&amp;bodytext=Rails%203.0.0%20now%20has%20a%20release%20candidate.%20These%20are%20the%20changes%20I%20made%20to%20a%20new%20application%20I%20am%20working%20on%20to%20clear%20up%20any%20deprecation%20warnings.%0D%0A%0D%0A%0D%0A%0D%0AGemfile%0D%0A%0D%0Agem%20%27rails%27%2C%20%273.0.0.rc%27%0D%0Agem%20%27haml%27%2C%20%273.0.14%27%0D%0A%0D%0AObviously%20you%20have%20to%20tell%20your%20applic" title="Digg"><img src="http://blog.agoragames.com/wp-content/plugins/var/www/waxer-blog/shared/wp-content/plugins/sociable/images/digg.png" title="Digg" alt="Digg" class="sociable-hovers" /></a>
	<a rel="nofollow"  target="_blank" href="http://delicious.com/post?url=http%3A%2F%2Fblog.agoragames.com%2F2010%2F07%2F27%2Frails-3-0-0-rc-changes%2F&amp;title=Rails%203.0.0.rc%20changes&amp;notes=Rails%203.0.0%20now%20has%20a%20release%20candidate.%20These%20are%20the%20changes%20I%20made%20to%20a%20new%20application%20I%20am%20working%20on%20to%20clear%20up%20any%20deprecation%20warnings.%0D%0A%0D%0A%0D%0A%0D%0AGemfile%0D%0A%0D%0Agem%20%27rails%27%2C%20%273.0.0.rc%27%0D%0Agem%20%27haml%27%2C%20%273.0.14%27%0D%0A%0D%0AObviously%20you%20have%20to%20tell%20your%20applic" title="del.icio.us"><img src="http://blog.agoragames.com/wp-content/plugins/var/www/waxer-blog/shared/wp-content/plugins/sociable/images/delicious.png" title="del.icio.us" alt="del.icio.us" class="sociable-hovers" /></a>
	<a rel="nofollow"  target="_blank" href="http://technorati.com/faves?add=http%3A%2F%2Fblog.agoragames.com%2F2010%2F07%2F27%2Frails-3-0-0-rc-changes%2F" title="Technorati"><img src="http://blog.agoragames.com/wp-content/plugins/var/www/waxer-blog/shared/wp-content/plugins/sociable/images/technorati.png" title="Technorati" alt="Technorati" class="sociable-hovers" /></a>


<br/><br/>]]></content:encoded>
			<wfw:commentRss>http://blog.agoragames.com/2010/07/27/rails-3-0-0-rc-changes/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Setting Up a Rails 3 Development Environment</title>
		<link>http://blog.agoragames.com/2010/06/24/setting-up-a-rails-3-development-environment/</link>
		<comments>http://blog.agoragames.com/2010/06/24/setting-up-a-rails-3-development-environment/#comments</comments>
		<pubDate>Thu, 24 Jun 2010 16:24:04 +0000</pubDate>
		<dc:creator>tquackenbush</dc:creator>
				<category><![CDATA[Bending Rails]]></category>
		<category><![CDATA[Engineering]]></category>
		<category><![CDATA[development]]></category>
		<category><![CDATA[install]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[rails3]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[rvm]]></category>
		<category><![CDATA[setup]]></category>

		<guid isPermaLink="false">http://blog.agoragames.com/?p=585</guid>
		<description><![CDATA[Getting started with Rails 3 development is a very straightforward process, granted you have the prerequisite version of Ruby installed on your system. Ruby Version Manager (RVM) is a utility that makes it very easy and painless to switch between Ruby versions while maintaining your system&#8217;s stock Ruby installation. RVM not only enables you to [...]]]></description>
			<content:encoded><![CDATA[<p><!-- code {   font-family: Courier New, Courier, mono; } pre {   font-family: Courier New, Courier, mono; } ul {   margin-bottom: 0; } ul li {    list-style: circle; } -->Getting started with Rails 3 development is a very straightforward process, granted you have the prerequisite version of Ruby installed on your system. <a href="http://rvm.beginrescueend.com">Ruby Version Manager</a> (RVM) is a utility that makes it very easy and painless to switch between Ruby versions while maintaining your system&#8217;s stock Ruby installation. RVM not only enables you to switch between Ruby versions, but also maintains distinct gem sets specific to each of those versions which is very helpful when testing out new Rails environments.</p>
<p>Before we jump into setup, first a bit about our pre-Rails3 environment:</p>
<ul>
<li>Mac OS X 10.5.8</li>
<li>ruby 1.8.6 (2009-06-08 patchlevel 369) [universal-darwin9.0] (stock)</li>
<li>RubyGems 1.3.7</li>
<li>Various older versions of Rails (2.3.8, 2.3.5, 2.3.4, 2.3.2, 2.2.2, 2.1.1, 2.1.0, 2.0.2, 1.2.6, 1.2.3)</li>
</ul>
<p>We will be installing the latest release of Rails which, as of this writing, is Rails 3 beta4.<br />
We will also complete setup using the latest version of Ruby 1.9.<br />
The minimal version of Ruby 1.9 required for this Rails release is 1.9.2.<br />
To complete setup with Ruby 1.8.7, consult the <a href="http://guides.rails.info/3_0_release_notes.html#rails-3-requires-at-least-ruby-187">Rails 3 release notes</a> for the minimal version requirements.</p>
<p>The basic installation steps are as follows:</p>
<ol>
<li>Install RVM (Ruby Version Manger)</li>
<li>Install Ruby 1.9.2</li>
<li>Install Rails3 beta4</li>
<li>Profit!</li>
</ol>
<p>To install, issue the following commands in a terminal window:</p>
<ol>
<li id="sidebar"><code>bash &lt; &lt;( curl http://rvm.beginrescueend.com/releases/rvm-install-head )</code>
<ul>
<li>This is the preferred RVM installation method as described in the <a href="http://rvm.beginrescueend.com/rvm/install/">RVM installation instructions</a>.</li>
</ul>
</li>
<li><code>rvm install 1.9.2-head</code></li>
<li><code>rvm 1.9.2-head</code></li>
<li><code>gem install rails --pre</code></li>
</ol>
<p>Installation of the rails gem should also install it&#8217;s respective dependencies:</p>
<pre>    [05:16:50][tquackenbush@TQuackenbush ~]$ gem list

    *** LOCAL GEMS ***
never
    abstract (1.0.0)
    actionmailer (3.0.0.beta4)
    actionpack (3.0.0.beta4)
    activemodel (3.0.0.beta4)
    activerecord (3.0.0.beta4)
    activeresource (3.0.0.beta4)
    activesupport (3.0.0.beta4)
    arel (0.4.0)
    builder (2.1.2)
    bundler (0.9.26)
    erubis (2.6.5)
    i18n (0.4.1)
    mail (2.2.5)
    mime-types (1.16)
    polyglot (0.3.1)
    rack (1.1.0)
    rack-mount (0.6.4)
    rack-test (0.5.4)
    rails (3.0.0.beta4)
    railties (3.0.0.beta4)
    rake (0.8.7)
    rdoc (2.5.8)
    thor (0.13.6)
    treetop (1.4.8)
    tzinfo (0.3.22)</pre>
<p>To test out your new installation, try creating a new bare bones Rails 3 application like so:</p>
<ol>
<li><code>rails new test_app</code></li>
<li><code>cd test_app</code></li>
<li><code>bundle install</code>
<ul>
<li>Bundler is the new default dependency manager in Rails 3, and will install any missing gems required by the project.</li>
<li>In my case, this was &#8217;sqlite3-ruby (1.3.0)&#8217;</li>
</ul>
</li>
<li><code>rails server</code></li>
</ol>
<p>As in Rails 2, this should launch a WEBrick server instance listening on localhost port 3000 with output similar to:</p>
<pre>    =&gt; Booting WEBrick
    =&gt; Rails 3.0.0.beta4 application starting in development on http://0.0.0.0:3000
    =&gt; Call with -d to detach
    =&gt; Ctrl-C to shutdown server
    [2010-06-23 16:54:06] INFO  WEBrick 1.3.1
    [2010-06-23 16:54:06] INFO  ruby 1.9.2 (2010-06-22) [i386-darwin9.8.0]
    [2010-06-23 16:54:06] INFO  WEBrick::HTTPServer#start: pid=6529 port=3000</pre>
<p>And that&#8217;s it! You&#8217;re all ready to go with Rails 3!</p>
<p><strong>Update: June 25th, 2010</strong> (David Czarnecki)</p>
<p>I ran into an issue on one system where rvm and Ruby 1.9.2 were correctly installed on the system, but Rails 3 would not install. The installation would go as follows.</p>
<blockquote>
<pre>machine-name:~ dczarnecki$ gem install rails --pre
WARNING:  RubyGems 1.2+ index not found for:

RubyGems will revert to legacy indexes degrading performance.</pre>
</blockquote>
<p>I blew away the ~/.gemrc file and Rails 3 installed successfully. YMMV.</p>
<p><strong>Update: June 29th, 2010</strong> (Joshua Childs)<br />
Ran into two issues with with dependencies while getting setup on my Ubuntu workstation.</p>
<p>First was while problem I ran into was while following the installation steps.</p>
<pre class="brush: bash">
# Command:
josh@jagar-tharn:~$ rvm install 1.9.2-head

# Response:
fail: bison is not available in your path. Please ensure it exists before compiling from head.

# Solution:
sudo apt-get install bison
</pre>
<p>And the second problem I ran into was while using bundle to setup my dependencies. My workstation did not have sqlite3 installed.</p>
<pre class="brush: bash">
# Command:
josh@jagar-tharn:~/projects/test_app$ bundle install

# Response:
...
Using rails (3.0.0.beta4) from bundler gems
Installing sqlite3-ruby (1.3.0) from rubygems repository at http://rubygems.org/ with native extensions /home/josh/.rvm/rubies/ruby-1.9.2-head/lib/ruby/1.9.1/rubygems/ext/builder.rb:46: warning: Insecure world writable dir /usr/local/libevent/ in PATH, mode 040777
/home/josh/.rvm/rubies/ruby-1.9.2-head/lib/ruby/1.9.1/rubygems/installer.rb:483:in `rescue in block in build_extensions&#039;: ERROR: Failed to build gem native extension. (Gem::Installer::ExtensionBuildError)

/home/josh/.rvm/rubies/ruby-1.9.2-head/bin/ruby extconf.rb
checking for sqlite3.h... no
sqlite3.h is missing. Try &#039;port install sqlite3 +universal&#039; or &#039;yum install sqlite3-devel&#039;
*** extconf.rb failed ***
Could not create Makefile due to some reason, probably lack of
necessary libraries and/or headers.  Check the mkmf.log file for more
details.  You may need configuration options.

Provided configuration options:
	--with-opt-dir
	--without-opt-dir
	--with-opt-include
	--without-opt-include=${opt-dir}/include
	--with-opt-lib
	--without-opt-lib=${opt-dir}/lib
	--with-make-prog
	--without-make-prog
	--srcdir=.
	--curdir
	--ruby=/home/josh/.rvm/rubies/ruby-1.9.2-head/bin/ruby
	--with-sqlite3-dir
	--without-sqlite3-dir
	--with-sqlite3-include
	--without-sqlite3-include=${sqlite3-dir}/include
	--with-sqlite3-lib
	--without-sqlite3-lib=${sqlite3-dir}/lib
...

# Solution:
josh@jagar-tharn:~/projects/test_app$ sudo apt-get install sqlite3
josh@jagar-tharn:~/projects/test_app$ sudo apt-get install libsqlite3-dev
</pre>




	<a rel="nofollow"  target="_blank" href="http://reddit.com/submit?url=http%3A%2F%2Fblog.agoragames.com%2F2010%2F06%2F24%2Fsetting-up-a-rails-3-development-environment%2F&amp;title=Setting%20Up%20a%20Rails%203%20Development%20Environment" title="Reddit"><img src="http://blog.agoragames.com/wp-content/plugins/var/www/waxer-blog/shared/wp-content/plugins/sociable/images/reddit.png" title="Reddit" alt="Reddit" class="sociable-hovers" /></a>
	<a rel="nofollow"  target="_blank" href="http://digg.com/submit?phase=2&amp;url=http%3A%2F%2Fblog.agoragames.com%2F2010%2F06%2F24%2Fsetting-up-a-rails-3-development-environment%2F&amp;title=Setting%20Up%20a%20Rails%203%20Development%20Environment&amp;bodytext=Getting%20started%20with%20Rails%203%20development%20is%20a%20very%20straightforward%20process%2C%20granted%20you%20have%20the%20prerequisite%20version%20of%20Ruby%20installed%20on%20your%20system.%20Ruby%20Version%20Manager%20%28RVM%29%20is%20a%20utility%20that%20makes%20it%20very%20easy%20and%20painless%20to%20switch%20between%20Rub" title="Digg"><img src="http://blog.agoragames.com/wp-content/plugins/var/www/waxer-blog/shared/wp-content/plugins/sociable/images/digg.png" title="Digg" alt="Digg" class="sociable-hovers" /></a>
	<a rel="nofollow"  target="_blank" href="http://delicious.com/post?url=http%3A%2F%2Fblog.agoragames.com%2F2010%2F06%2F24%2Fsetting-up-a-rails-3-development-environment%2F&amp;title=Setting%20Up%20a%20Rails%203%20Development%20Environment&amp;notes=Getting%20started%20with%20Rails%203%20development%20is%20a%20very%20straightforward%20process%2C%20granted%20you%20have%20the%20prerequisite%20version%20of%20Ruby%20installed%20on%20your%20system.%20Ruby%20Version%20Manager%20%28RVM%29%20is%20a%20utility%20that%20makes%20it%20very%20easy%20and%20painless%20to%20switch%20between%20Rub" title="del.icio.us"><img src="http://blog.agoragames.com/wp-content/plugins/var/www/waxer-blog/shared/wp-content/plugins/sociable/images/delicious.png" title="del.icio.us" alt="del.icio.us" class="sociable-hovers" /></a>
	<a rel="nofollow"  target="_blank" href="http://technorati.com/faves?add=http%3A%2F%2Fblog.agoragames.com%2F2010%2F06%2F24%2Fsetting-up-a-rails-3-development-environment%2F" title="Technorati"><img src="http://blog.agoragames.com/wp-content/plugins/var/www/waxer-blog/shared/wp-content/plugins/sociable/images/technorati.png" title="Technorati" alt="Technorati" class="sociable-hovers" /></a>


<br/><br/>]]></content:encoded>
			<wfw:commentRss>http://blog.agoragames.com/2010/06/24/setting-up-a-rails-3-development-environment/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Packaging For Pleasure</title>
		<link>http://blog.agoragames.com/2010/04/19/packaging-for-pleasure/</link>
		<comments>http://blog.agoragames.com/2010/04/19/packaging-for-pleasure/#comments</comments>
		<pubDate>Mon, 19 Apr 2010 20:15:11 +0000</pubDate>
		<dc:creator>David Czarnecki</dc:creator>
				<category><![CDATA[Bending Rails]]></category>
		<category><![CDATA[Engineering]]></category>
		<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[application]]></category>
		<category><![CDATA[packaging]]></category>
		<category><![CDATA[rails]]></category>

		<guid isPermaLink="false">http://blog.agoragames.com/?p=540</guid>
		<description><![CDATA[Let me be more explicit and say I&#8217;m going to be talking about Rails application packaging. Sorry, I needed a good post title for the lulz and the page views.

There are a few rake tasks that I&#8217;ve been using more and more now that all of our applications are running in a shared, virtual enviroment. [...]]]></description>
			<content:encoded><![CDATA[<p>Let me be more explicit and say I&#8217;m going to be talking about Rails application packaging. Sorry, I needed a good post title for the lulz and the page views.</p>
<p><span id="more-540"></span></p>
<p>There are a few rake tasks that I&#8217;ve been using more and more now that all of our applications are running in a shared, virtual enviroment. They are:</p>
<p>* rake -T     # -T, &#8211;tasks [PATTERN]            Display the tasks (matching optional PATTERN) with descriptions, then exit.</p>
<p>Everyone should know and use this task at least once in their Rails-development life.</p>
<p>* rake rails:freeze:gems   # Lock this application to the current gems (by unpacking them into vendor/rails)<br />
* rake gems:unpack   # Unpacks all required gems into vendor/gems.<br />
* rake gems:unpack:dependencies   # Unpacks all required gems and their dependencies into vendor/gems.</p>
<p>So, once I&#8217;ve created my project with &#8220;rails [project name]&#8220;, then next thing I do is &#8220;rake rails:freeze:gems&#8221; to freeze the Rails gems. I&#8217;ll enumerate the application&#8217;s dependencies in the environment.rb file and then run &#8220;rake gems:unpack&#8221; to make sure those dependencies exist with the application. Example:</p>
<pre class="brush: ruby">

config.gem &#039;will_paginate&#039;, :version =&gt; &#039;2.3.11&#039;, :source =&gt; &#039;http://gemcutter.org&#039;
config.gem &#039;factory_girl&#039;, :version =&gt; &#039;1.2.4&#039;, :source =&gt; &#039;http://gemcutter.org&#039;
config.gem &#039;fakeweb&#039;, :version =&gt; &#039;1.2.8&#039;, :source =&gt; &#039;http://gemcutter.org&#039;
</pre>
<p>Why do I like this approach? In a shared environment, it means we don&#8217;t have to have our systems folks install any dependencies for our application to run making the application self-contained. This is mostly fine for gems that don&#8217;t have an explicit native component. Also, in being explicit about versions of the gems that an application is using, we do not run the risk of chasing a moving target. Again, in a shared environment, if someone updates a gem on the system, it&#8217;s probably not an issue until the one time it is and you&#8217;re being called at 3 AM that the application is down because of a gem incompatibility change.</p>
<p>That&#8217;s it. Any other packaging dos and don&#8217;t?</p>




	<a rel="nofollow"  target="_blank" href="http://reddit.com/submit?url=http%3A%2F%2Fblog.agoragames.com%2F2010%2F04%2F19%2Fpackaging-for-pleasure%2F&amp;title=Packaging%20For%20Pleasure" title="Reddit"><img src="http://blog.agoragames.com/wp-content/plugins/var/www/waxer-blog/shared/wp-content/plugins/sociable/images/reddit.png" title="Reddit" alt="Reddit" class="sociable-hovers" /></a>
	<a rel="nofollow"  target="_blank" href="http://digg.com/submit?phase=2&amp;url=http%3A%2F%2Fblog.agoragames.com%2F2010%2F04%2F19%2Fpackaging-for-pleasure%2F&amp;title=Packaging%20For%20Pleasure&amp;bodytext=Let%20me%20be%20more%20explicit%20and%20say%20I%27m%20going%20to%20be%20talking%20about%20Rails%20application%20packaging.%20Sorry%2C%20I%20needed%20a%20good%20post%20title%20for%20the%20lulz%20and%20the%20page%20views.%0D%0A%0D%0A%0D%0A%0D%0AThere%20are%20a%20few%20rake%20tasks%20that%20I%27ve%20been%20using%20more%20and%20more%20now%20that%20all%20of%20our%20app" title="Digg"><img src="http://blog.agoragames.com/wp-content/plugins/var/www/waxer-blog/shared/wp-content/plugins/sociable/images/digg.png" title="Digg" alt="Digg" class="sociable-hovers" /></a>
	<a rel="nofollow"  target="_blank" href="http://delicious.com/post?url=http%3A%2F%2Fblog.agoragames.com%2F2010%2F04%2F19%2Fpackaging-for-pleasure%2F&amp;title=Packaging%20For%20Pleasure&amp;notes=Let%20me%20be%20more%20explicit%20and%20say%20I%27m%20going%20to%20be%20talking%20about%20Rails%20application%20packaging.%20Sorry%2C%20I%20needed%20a%20good%20post%20title%20for%20the%20lulz%20and%20the%20page%20views.%0D%0A%0D%0A%0D%0A%0D%0AThere%20are%20a%20few%20rake%20tasks%20that%20I%27ve%20been%20using%20more%20and%20more%20now%20that%20all%20of%20our%20app" title="del.icio.us"><img src="http://blog.agoragames.com/wp-content/plugins/var/www/waxer-blog/shared/wp-content/plugins/sociable/images/delicious.png" title="del.icio.us" alt="del.icio.us" class="sociable-hovers" /></a>
	<a rel="nofollow"  target="_blank" href="http://technorati.com/faves?add=http%3A%2F%2Fblog.agoragames.com%2F2010%2F04%2F19%2Fpackaging-for-pleasure%2F" title="Technorati"><img src="http://blog.agoragames.com/wp-content/plugins/var/www/waxer-blog/shared/wp-content/plugins/sociable/images/technorati.png" title="Technorati" alt="Technorati" class="sociable-hovers" /></a>


<br/><br/>]]></content:encoded>
			<wfw:commentRss>http://blog.agoragames.com/2010/04/19/packaging-for-pleasure/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Getting started with data_fabric</title>
		<link>http://blog.agoragames.com/2010/01/29/getting-started-with-data_fabric/</link>
		<comments>http://blog.agoragames.com/2010/01/29/getting-started-with-data_fabric/#comments</comments>
		<pubDate>Fri, 29 Jan 2010 15:46:01 +0000</pubDate>
		<dc:creator>David Czarnecki</dc:creator>
				<category><![CDATA[Bending Rails]]></category>
		<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[active_record]]></category>
		<category><![CDATA[database]]></category>
		<category><![CDATA[data_fabric]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[sharding]]></category>

		<guid isPermaLink="false">http://blog.agoragames.com/?p=447</guid>
		<description><![CDATA[The data_fabric gem &#8220;provides flexible database connection switching for ActiveRecord&#8221;. If you&#8217;re not concerned with database sharding, you might want to skip this blog post. Or not. Either way, I&#8217;m not going to be offended.
I have a requirement that certain data in an application that I&#8217;m developing will probably have to be sharded because, if [...]]]></description>
			<content:encoded><![CDATA[<p>The <a href="http://github.com/mperham/data_fabric">data_fabric</a> gem &#8220;provides flexible database connection switching for ActiveRecord&#8221;. If you&#8217;re not concerned with database sharding, you might want to skip this blog post. Or not. Either way, I&#8217;m not going to be offended.</p>
<p>I have a requirement that certain data in an application that I&#8217;m developing will probably have to be sharded because, if you&#8217;ll excuse my English, there will a &#8220;shit ton&#8221; of data. This only affects one model out of the few models I have in the application. I don&#8217;t have a requirement that the data will be replicated (which is another feature supported in data_fabric), so I&#8217;m not going into that here. In any event, here is a rundown of how I got started developing and testing with data_fabric.</p>
<p>- Configure the data_fabric gem in your config/environment.rb file.</p>
<pre class="brush: ruby">

config.gem &#039;data_fabric&#039;
</pre>
<p>- In your model(s), decide on which column or how the data is going to be shared.</p>
<pre class="brush: ruby">

data_fabric :replicated =&gt; false, :shard_by =&gt; :initial_code
</pre>
<p>In this case, inital_code is a method that looks at a piece of the model&#8217;s data and gives me the correct shard.</p>
<p>- Setup the database shards in your config/database.yml file. I actually setup only one shard for development and testing environments to make things easier. I&#8217;m just including the one for the test environment here. You can read on the data_fabric site about the naming convention for sharded database connections.</p>
<pre class="brush: sql">

test:
adapter: mysql
encoding: utf8
reconnect: false
database: myapp_test
pool: 5
username: root
password:

# This is the database shard
initial_code_testenv_test:
adapter: mysql
encoding: utf8
reconnect: false
database: myapp_test_testenv
pool: 5
username: root
password:
</pre>
<p>- In config/initializers/my_app_model.rb, I actually stub out the initial_code method to return a single value for the development and test environments. This is merely convenience so I don&#8217;t have to include every single database shard for development and testing.</p>
<pre class="brush: ruby">

require &#039;mocha&#039;

if &#039;development&#039;.eql?(RAILS_ENV)
PromotionCode.stubs(:initial_code).returns(&#039;devenv&#039;)
end

if &#039;test&#039;.eql?(RAILS_ENV)
PromotionCode.stubs(:initial_code).returns(&#039;testenv&#039;)
end
</pre>
<p>- I copied part of the Rakefile from the data_fabric gem to actually be able to migrate the database for the sharded database connections. This was definitely missing from the data_fabric README.</p>
<pre class="brush: ruby">

require &#039;fileutils&#039;
include FileUtils::Verbose

namespace :db do
task :migrate do
require &#039;erb&#039;
require &#039;logger&#039;
require &#039;active_record&#039;
reference = YAML::load(ERB.new(IO.read(&quot;config/database.yml&quot;)).result)
env = RAILS_ENV = ENV[&#039;RAILS_ENV&#039;] || &#039;development&#039;
ActiveRecord::Base.logger = Logger.new(STDOUT)
ActiveRecord::Base.logger.level = Logger::WARN
ActiveRecord::Base.configurations = reference.dup
old_config = reference[env]
reference.each_key do |name|
next unless name.include? env
next if name.include? &#039;slave&#039; # Replicated databases should not be touched directly

puts &quot;Migrating #{name}&quot;
ActiveRecord::Base.clear_active_connections!
ActiveRecord::Base.configurations[env] = reference[name]
ActiveRecord::Base.establish_connection RAILS_ENV
ActiveRecord::Migration.verbose = ENV[&quot;VERBOSE&quot;] ? ENV[&quot;VERBOSE&quot;] == &quot;true&quot; : true
ActiveRecord::Migrator.migrate(&quot;db/migrate/&quot;, ENV[&quot;VERSION&quot;] ? ENV[&quot;VERSION&quot;].to_i : nil)
end
end
end
</pre>
<p>- In my test classes that use the sharded model, I have setup and teardown methods that activate and deactivate the shard.</p>
<pre class="brush: ruby">

def setup
DataFabric.activate_shard(:initial_code =&gt; &#039;testenv&#039;)
end

def teardown
MyAppModel.delete_all
DataFabric.deactivate_shard(:initial_code =&gt; &#039;testenv&#039;)
end
</pre>
<p>I did find that I needed to delete all the objects in the database for the sharded model. I&#8217;m still digging into why that&#8217;s the case. My ActiveRecord_fu isn&#8217;t that strong I guess.</p>
<p>All in all, sharding is relatively easy with data_fabric. Pimping, however, &#8220;ain&#8217;t easy.&#8221; But that&#8217;s for another blog post I guess.</p>




	<a rel="nofollow"  target="_blank" href="http://reddit.com/submit?url=http%3A%2F%2Fblog.agoragames.com%2F2010%2F01%2F29%2Fgetting-started-with-data_fabric%2F&amp;title=Getting%20started%20with%20data_fabric" title="Reddit"><img src="http://blog.agoragames.com/wp-content/plugins/var/www/waxer-blog/shared/wp-content/plugins/sociable/images/reddit.png" title="Reddit" alt="Reddit" class="sociable-hovers" /></a>
	<a rel="nofollow"  target="_blank" href="http://digg.com/submit?phase=2&amp;url=http%3A%2F%2Fblog.agoragames.com%2F2010%2F01%2F29%2Fgetting-started-with-data_fabric%2F&amp;title=Getting%20started%20with%20data_fabric&amp;bodytext=The%20data_fabric%20gem%20%22provides%20flexible%20database%20connection%20switching%20for%20ActiveRecord%22.%20If%20you%27re%20not%20concerned%20with%20database%20sharding%2C%20you%20might%20want%20to%20skip%20this%20blog%20post.%20Or%20not.%20Either%20way%2C%20I%27m%20not%20going%20to%20be%20offended.%0D%0A%0D%0AI%20have%20a%20requirement%20t" title="Digg"><img src="http://blog.agoragames.com/wp-content/plugins/var/www/waxer-blog/shared/wp-content/plugins/sociable/images/digg.png" title="Digg" alt="Digg" class="sociable-hovers" /></a>
	<a rel="nofollow"  target="_blank" href="http://delicious.com/post?url=http%3A%2F%2Fblog.agoragames.com%2F2010%2F01%2F29%2Fgetting-started-with-data_fabric%2F&amp;title=Getting%20started%20with%20data_fabric&amp;notes=The%20data_fabric%20gem%20%22provides%20flexible%20database%20connection%20switching%20for%20ActiveRecord%22.%20If%20you%27re%20not%20concerned%20with%20database%20sharding%2C%20you%20might%20want%20to%20skip%20this%20blog%20post.%20Or%20not.%20Either%20way%2C%20I%27m%20not%20going%20to%20be%20offended.%0D%0A%0D%0AI%20have%20a%20requirement%20t" title="del.icio.us"><img src="http://blog.agoragames.com/wp-content/plugins/var/www/waxer-blog/shared/wp-content/plugins/sociable/images/delicious.png" title="del.icio.us" alt="del.icio.us" class="sociable-hovers" /></a>
	<a rel="nofollow"  target="_blank" href="http://technorati.com/faves?add=http%3A%2F%2Fblog.agoragames.com%2F2010%2F01%2F29%2Fgetting-started-with-data_fabric%2F" title="Technorati"><img src="http://blog.agoragames.com/wp-content/plugins/var/www/waxer-blog/shared/wp-content/plugins/sociable/images/technorati.png" title="Technorati" alt="Technorati" class="sociable-hovers" /></a>


<br/><br/>]]></content:encoded>
			<wfw:commentRss>http://blog.agoragames.com/2010/01/29/getting-started-with-data_fabric/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Scaling Ruby and Rails Part 1</title>
		<link>http://blog.agoragames.com/2010/01/04/scaling-ruby-and-rails-part-1/</link>
		<comments>http://blog.agoragames.com/2010/01/04/scaling-ruby-and-rails-part-1/#comments</comments>
		<pubDate>Mon, 04 Jan 2010 23:34:21 +0000</pubDate>
		<dc:creator>David Czarnecki</dc:creator>
				<category><![CDATA[Bending Rails]]></category>
		<category><![CDATA[Engineering]]></category>
		<category><![CDATA[amqp]]></category>
		<category><![CDATA[deep dive]]></category>
		<category><![CDATA[rabbit]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[scaling]]></category>

		<guid isPermaLink="false">http://blog.agoragames.com/?p=421</guid>
		<description><![CDATA[I wish scaling applications and systems these days consisted solely of &#8220;Just Add Scaling!&#8220;. But you know what? It&#8217;s not. I also forget where I read it, but the quote went something like, &#8220;Programming languages don&#8217;t scale, architectures scale.&#8221; Scaling is driven by proper iterative design, implementation and testing.
In a series of blog posts I [...]]]></description>
			<content:encoded><![CDATA[<p>I wish scaling applications and systems these days consisted solely of &#8220;<a href="http://olabini.com/blog/2008/05/just-add-scaling/">Just Add Scaling!</a>&#8220;. But you know what? It&#8217;s not. I also forget where I read it, but the quote went something like, &#8220;Programming languages don&#8217;t scale, architectures scale.&#8221; Scaling is driven by proper iterative design, implementation and testing.</p>
<p>In a series of blog posts I want to cover how we have approached scaling out various parts of our Ruby and Rails infrastructure here at Agora Games using real-world examples on very high-traffic sites such as the Guitar Hero and Call of Duty community sites.</p>
<p>Here I&#8217;ll cover the &#8220;Deep Dive&#8221;. I originally came from BigCo. and there we used a concept called the &#8220;Deep Dive&#8221;, which involved taking a specific requirement in combination with an approach or technology and following a thread of execution that would take you through the entire technology stack, or a &#8220;<span>deep</span> <span>dive</span>&#8221; through the system. At the end you would either prove or disprove the technology or approach. But it was done in the context of a real set of requirements.</p>
<p>The following is the e-mail (project/features names changed to protect the innocent &#8230; the important concept here is the Deep Dive, not the project/features) I sent around to our engineering team in September of last year after doing a Deep Dive on a queue system.</p>
<p>_________________</p>
<p><span style="text-decoration: underline;"> </span></p>
<blockquote><p>From: David Czarnecki</p>
<p>To: Engineering</p>
<p><span style="text-decoration: underline;">Clearly Defined Requirement(s)</span></p>
<p>Ultimately, to do a deep dive correctly, you need clearly defined requirements to evaluate your technology or approach against. In the case of PROJECT X, with the use of a queue, we had the following:</p>
<p>Setup queue<br />
Decide event(s)<br />
Send to queue<br />
Aggregate from/to queue<br />
Put into message creation<br />
Send back to the app</p>
<p><span style="text-decoration: underline;">Narrowing the Field</span></p>
<p>I spent a day looking at various queue packages in Ruby and other languages to understand:</p>
<p>Features &#8211; What features do we get out of the package?<br />
API &#8211; How easy is it to setup/create/interact with the queue from actual code?<br />
Aliveness &#8211; Is this an ongoing effort or was it thrown on RubyForge and ultimately abandoned?<br />
Community &#8211; Where is this package being used? How many developers or contributors commit to the project?<br />
Language &#8211; Are we expanding our technology stack by introducing a queue written in one language with an interface in another language?</p>
<p><span style="text-decoration: underline;">Pork, aka The Other Other Requirements</span></p>
<p>And don&#8217;t forget about the other &#8220;unspoken&#8221; requirements.</p>
<p>Ease of setup<br />
Speed<br />
Failsafe<br />
Scaling</p>
<p>At the end of the day, whichever package is picked, you want some guarantee that the package you&#8217;ve chosen is &#8220;good&#8221; or at least &#8220;good enough&#8221;. But what if the Guarantee Fairy&#8217;s a crazy glue sniffer? Next thing you know there&#8217;s change missing from your dresser and your daughter&#8217;s knocked up. I&#8217;ve seen it a hundred times. Although you&#8217;ve got a set of requirements that define how you&#8217;re going to use a technology or approach operationally, there are still requirements that need to be addressed, even if there isn&#8217;t anything formally specified.</p>
<p><span style="text-decoration: underline;">Let&#8217;s Get Ready To Rumble</span></p>
<p>I chose Sparrow and Rabbit/AMQP since these passed the &#8220;ease of setup&#8221; requirements with flying colors.</p>
<p><a href="http://code.google.com/p/sparrow/">http://code.google.com/p/sparrow/</a><br />
- Pure Ruby<br />
<a href="http://hopper.squarespace.com/blog/2008/7/22/simple-amqp-library-for-ruby.html"> http://hopper.squarespace.com/blog/2008/7/22/simple-amqp-library-for-ruby.html</a><br />
- Erlang Queue Server/Ruby interface to Queue</p>
<p>Next up it was time to prove out the feasibility of the two technologies looking at the &#8220;soft&#8221; requirements in the context of the &#8220;hard&#8221; requirements. This meant setting up the two systems to:</p>
<p>Setup queue<br />
Send event(s) to queue<br />
Aggregate from/to queue</p>
<p>The other &#8220;hard&#8221; requirements would be addressed based on the outcome of this initial sanity check.</p>
<p><span style="text-decoration: underline;">2 Queues Enter, 1 Queue Leaves &#8230; Wait, what?</span></p>
<p>Although I wanted to use this to prove out &#8220;FEATURE X&#8221;, I also wanted to address its use in &#8220;FEATURE Y&#8221;. &#8220;FEATURE Y&#8221; involves converting a song file into an MP3. So I setup a test to evaluate the two systems which was:</p>
<pre class="brush: ruby">

1k, 8k, 16k, 32k, 64k messages do
25.times do
10000 messages do
publish message to queue
read message from queue
end
end
end
</pre>
<p>In other words, publish 10000 messages to the queue (in one process) and read those messages from the queue (in another process), noting how long it took to publish and read. Do this 25 times to get a min/max/average time for each of the different message sizes.</p>
<p>I have attached the spreadsheet of the results which show: the larger the message, the longer it takes to publish and read from the queue. However, it also shows that Sparrow could handle the 64k messages while Rabbit/AMQP could not. Sparrow got slower to process those 10000 64k items from the queue, but it never failed as with Rabbit/AMQP. Ultimately, the deep dive was not about fixing a broken AMQP adapter.</p>
<p><span style="text-decoration: underline;">The Devil is in the Details</span></p>
<p>One benefit of using Sparrow is that persistence is built into the server. If you take down Sparrow and there are messages on the queue, it will write those out to an SQLite3 database. Ultimately this lead me to look at the size of the field it was using for queue data which would need to be patched from its current 255 characters.</p>
<p><span style="text-decoration: underline;">Conclusion</span></p>
<p>So, I&#8217;ve now got a queue server that I feel comfortable setting up and using and that can probably handle the load of data we&#8217;re going to throw at it come launch. The queue server/queues were integrated into PROJECT X in the context of the &#8220;FEATURE X&#8221; to prove its feasibility in addressing that feature in a future sprint.</p>
<p><span style="text-decoration: underline;">And one more thing &#8230;</span></p>
<p>There are tests for the various bits that make up &#8220;FEATURE X&#8221;. I&#8217;m most happy with the integration test which fires up a Sparrow server, fires up a foo, creates a bar, runs the aggregator, and checks to see that a baz was created for the account (oh and then cleaning up the queue server and the subscriber). 14 LOC, but there&#8217;s a lot of code that it exercises behind the scenes. And yes, it passes :)</p></blockquote>
<p><span style="text-decoration: underline;"> </span></p>
<p>_________________</p>
<p>So, there you go. Hopefully you have enough information to do your own Deep Dive.</p>
<p>Ultimately for FEATURE X and FEATURE Y, Sparrow more than met our needs. Advances and changes to AMQP and its associated libraries have been made which I&#8217;m sure make it a more than viable candidate. At the time however, with just getting the system to work for a day to prove out the Deep Dive, it just didn&#8217;t meet our needs. Again, the point of this blog post is to talk about the Deep Dive in the larger context of its use in Scaling Ruby and Rails.</p>




	<a rel="nofollow"  target="_blank" href="http://reddit.com/submit?url=http%3A%2F%2Fblog.agoragames.com%2F2010%2F01%2F04%2Fscaling-ruby-and-rails-part-1%2F&amp;title=Scaling%20Ruby%20and%20Rails%20Part%201" title="Reddit"><img src="http://blog.agoragames.com/wp-content/plugins/var/www/waxer-blog/shared/wp-content/plugins/sociable/images/reddit.png" title="Reddit" alt="Reddit" class="sociable-hovers" /></a>
	<a rel="nofollow"  target="_blank" href="http://digg.com/submit?phase=2&amp;url=http%3A%2F%2Fblog.agoragames.com%2F2010%2F01%2F04%2Fscaling-ruby-and-rails-part-1%2F&amp;title=Scaling%20Ruby%20and%20Rails%20Part%201&amp;bodytext=I%20wish%20scaling%20applications%20and%20systems%20these%20days%20consisted%20solely%20of%20%22Just%20Add%20Scaling%21%22.%20But%20you%20know%20what%3F%20It%27s%20not.%20I%20also%20forget%20where%20I%20read%20it%2C%20but%20the%20quote%20went%20something%20like%2C%20%22Programming%20languages%20don%27t%20scale%2C%20architectures%20scale.%22%20Scali" title="Digg"><img src="http://blog.agoragames.com/wp-content/plugins/var/www/waxer-blog/shared/wp-content/plugins/sociable/images/digg.png" title="Digg" alt="Digg" class="sociable-hovers" /></a>
	<a rel="nofollow"  target="_blank" href="http://delicious.com/post?url=http%3A%2F%2Fblog.agoragames.com%2F2010%2F01%2F04%2Fscaling-ruby-and-rails-part-1%2F&amp;title=Scaling%20Ruby%20and%20Rails%20Part%201&amp;notes=I%20wish%20scaling%20applications%20and%20systems%20these%20days%20consisted%20solely%20of%20%22Just%20Add%20Scaling%21%22.%20But%20you%20know%20what%3F%20It%27s%20not.%20I%20also%20forget%20where%20I%20read%20it%2C%20but%20the%20quote%20went%20something%20like%2C%20%22Programming%20languages%20don%27t%20scale%2C%20architectures%20scale.%22%20Scali" title="del.icio.us"><img src="http://blog.agoragames.com/wp-content/plugins/var/www/waxer-blog/shared/wp-content/plugins/sociable/images/delicious.png" title="del.icio.us" alt="del.icio.us" class="sociable-hovers" /></a>
	<a rel="nofollow"  target="_blank" href="http://technorati.com/faves?add=http%3A%2F%2Fblog.agoragames.com%2F2010%2F01%2F04%2Fscaling-ruby-and-rails-part-1%2F" title="Technorati"><img src="http://blog.agoragames.com/wp-content/plugins/var/www/waxer-blog/shared/wp-content/plugins/sociable/images/technorati.png" title="Technorati" alt="Technorati" class="sociable-hovers" /></a>


<br/><br/>]]></content:encoded>
			<wfw:commentRss>http://blog.agoragames.com/2010/01/04/scaling-ruby-and-rails-part-1/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>RailsConf Wrap Up</title>
		<link>http://blog.agoragames.com/2009/05/29/railsconf-wrap-up/</link>
		<comments>http://blog.agoragames.com/2009/05/29/railsconf-wrap-up/#comments</comments>
		<pubDate>Fri, 29 May 2009 17:42:50 +0000</pubDate>
		<dc:creator>Jason LaPorte</dc:creator>
				<category><![CDATA[Engineering]]></category>
		<category><![CDATA[Infrastructure]]></category>
		<category><![CDATA[deploy]]></category>
		<category><![CDATA[monit]]></category>
		<category><![CDATA[overlord]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[railsconf]]></category>
		<category><![CDATA[rrd]]></category>
		<category><![CDATA[sysadmin]]></category>
		<category><![CDATA[unix]]></category>

		<guid isPermaLink="false">http://blog.agoragames.com/?p=281</guid>
		<description><![CDATA[Well, we&#8217;re back from Vegas! And have been, for a couple weeks&#8230; I&#8217;ve been meaning to put up some follow-up resources for my talk (PWN Your Infrastructure: Behind Call of Duty: World at War), but there was just so much work to do when I got back&#8230; such is the life of a system administrator!
That said, I&#8217;ve [...]]]></description>
			<content:encoded><![CDATA[<p>Well, we&#8217;re back from Vegas! And have been, for a couple weeks&#8230; I&#8217;ve been meaning to put up some follow-up resources for my talk (<em>PWN Your Infrastructure: Behind Call of Duty: World at War</em>), but there was just so much work to do when I got back&#8230; such is the life of a system administrator!</p>
<p>That said, I&#8217;ve got some free moments, so I&#8217;m putting up some reference materials.</p>
<p><span id="more-281"></span></p>
<p>Anyway, for those who didn&#8217;t see it, my talk was about the cloud infrastructure we built to power the <a href="http://callofduty.com/" target="_blank">Call of Duty stats site</a>, and the tools we built to support that. The slides from the talk are available <a href="http://files.agoragames.com/jason/railsconf09/" target="_blank">here</a>, though they probably don&#8217;t mean too much without the audio behind them.</p>
<p>The puzzle pieces I talked about were:</p>
<ul>
<li><a href="http://en.wikipedia.org/wiki/Cloud_computing" target="_blank">Virtualization</a>, which allowed us to not have to worry about hardware failures (and gave us a lot of flexibility unrelated to scaling, such as being able to instantly clone a test environment, do some testing, and shut it back down, for virtually no cost). <a href="http://www.terremark.com/" target="_blank">Terremark</a> is our awesome hosting provider.</li>
<li><a href="http://en.wikipedia.org/wiki/Network_File_System_(protocol)" target="_self">NFS</a>, which allowed us to do away with complicated tools like <a href="http://www.capify.org/" target="_blank">Capistrano</a> and avoid managing server installations separately. It&#8217;s been around for 25 years, so it&#8217;s stable, and it&#8217;s also dead simple. Unfortunately, it is not suitable for tasks requiring heavy IO or a very large number of files, so it must be used with care.</li>
<li><a href="http://mmonit.com/monit/" target="_blank">Monit</a>, which allowed us to monitor our hosts and automatically fix certain problems (such as application failures) without requiring human intervention. As mentioned in the slides, if you want to pull XML from Monit (which we do to aggregate data from all of our hosts), the URL or doing so is &#8220;/_status?format=xml&#8221;. <em>This behavior is not documented.</em></li>
<li>Overlord, a simple internal tool that distributes server configuration and aggregates monitoring information from each Monit instance. Overlord is currently proprietary, but we&#8217;re considering releasing it once it&#8217;s ready (read: once it&#8217;s properly documented). But it&#8217;s really simple. It basically says what files should be on which servers (all of which are just simple text files), and they&#8217;re placed there on boot. Any files put into a particular directory are run as scripts. After that, it&#8217;s just a big cron job to pull XML from all of our servers and make pretty graphs.</li>
<li><a href="http://oss.oetiker.ch/rrdtool/" target="_blank">RRDTool</a>, which has many uses, but specifically makes the aforementioned pretty graphs. These are vital to determine trends and validate results. Also, they&#8217;re really pretty. Double also, RRDTool is extremely well constructed and totally awesome.</li>
<li>Using shell scripts everywhere. Thanks to using NFS, Monit, and Overlord, our distribution needs are already taken care of, so we can do a <strong>lot</strong> via simple shell scripts, which makes our infrastructure self-documenting and easy to work with. The simplest example of this is that we switched to deploying our applications with shell scripts, instead of using Capistrano or other network tools.</li>
</ul>
<p>The end result is a scalable system that, while it still has a few warts we&#8217;re working through, is very simple, self-documenting, and easy for even a non-sys-admin to diagnose and solve problems on&#8211;there&#8217;s very little magic here, just some elegant abstractions.</p>
<p>Some people were interested in getting some more information on our deploy scripts, so I&#8217;ve made them <a href="http://files.agoragames.com/jason/deploy/" target="_blank">available online</a>. They come in two parts: &#8220;core.sh&#8221; defines the core set of functionality, for logging, rollbacks, and some basic &#8220;here&#8217;s how you deploy Rails 101&#8243; functions. &#8220;deploy.sh&#8221; actually performs the deploy itself, and is the script that should be executed.</p>
<p>All told, we had a blast, and are looking forward to future RailsConfs!</p>




	<a rel="nofollow"  target="_blank" href="http://reddit.com/submit?url=http%3A%2F%2Fblog.agoragames.com%2F2009%2F05%2F29%2Frailsconf-wrap-up%2F&amp;title=RailsConf%20Wrap%20Up" title="Reddit"><img src="http://blog.agoragames.com/wp-content/plugins/var/www/waxer-blog/shared/wp-content/plugins/sociable/images/reddit.png" title="Reddit" alt="Reddit" class="sociable-hovers" /></a>
	<a rel="nofollow"  target="_blank" href="http://digg.com/submit?phase=2&amp;url=http%3A%2F%2Fblog.agoragames.com%2F2009%2F05%2F29%2Frailsconf-wrap-up%2F&amp;title=RailsConf%20Wrap%20Up&amp;bodytext=Well%2C%20we%27re%20back%20from%20Vegas%21%20And%20have%20been%2C%20for%20a%20couple%20weeks...%C2%A0I%27ve%20been%20meaning%20to%20put%20up%20some%20follow-up%20resources%20for%20my%20talk%20%28PWN%20Your%20Infrastructure%3A%20Behind%20Call%20of%20Duty%3A%20World%C2%A0at%20War%29%2C%20but%20there%20was%20just%20so%20much%20work%20to%20do%20when%20I%20got%20back.." title="Digg"><img src="http://blog.agoragames.com/wp-content/plugins/var/www/waxer-blog/shared/wp-content/plugins/sociable/images/digg.png" title="Digg" alt="Digg" class="sociable-hovers" /></a>
	<a rel="nofollow"  target="_blank" href="http://delicious.com/post?url=http%3A%2F%2Fblog.agoragames.com%2F2009%2F05%2F29%2Frailsconf-wrap-up%2F&amp;title=RailsConf%20Wrap%20Up&amp;notes=Well%2C%20we%27re%20back%20from%20Vegas%21%20And%20have%20been%2C%20for%20a%20couple%20weeks...%C2%A0I%27ve%20been%20meaning%20to%20put%20up%20some%20follow-up%20resources%20for%20my%20talk%20%28PWN%20Your%20Infrastructure%3A%20Behind%20Call%20of%20Duty%3A%20World%C2%A0at%20War%29%2C%20but%20there%20was%20just%20so%20much%20work%20to%20do%20when%20I%20got%20back.." title="del.icio.us"><img src="http://blog.agoragames.com/wp-content/plugins/var/www/waxer-blog/shared/wp-content/plugins/sociable/images/delicious.png" title="del.icio.us" alt="del.icio.us" class="sociable-hovers" /></a>
	<a rel="nofollow"  target="_blank" href="http://technorati.com/faves?add=http%3A%2F%2Fblog.agoragames.com%2F2009%2F05%2F29%2Frailsconf-wrap-up%2F" title="Technorati"><img src="http://blog.agoragames.com/wp-content/plugins/var/www/waxer-blog/shared/wp-content/plugins/sociable/images/technorati.png" title="Technorati" alt="Technorati" class="sociable-hovers" /></a>


<br/><br/>]]></content:encoded>
			<wfw:commentRss>http://blog.agoragames.com/2009/05/29/railsconf-wrap-up/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Write if read returns nil</title>
		<link>http://blog.agoragames.com/2009/05/13/write-if-read-returns-nil/</link>
		<comments>http://blog.agoragames.com/2009/05/13/write-if-read-returns-nil/#comments</comments>
		<pubDate>Wed, 13 May 2009 14:14:00 +0000</pubDate>
		<dc:creator>Ola Mork</dc:creator>
				<category><![CDATA[Bending Rails]]></category>
		<category><![CDATA[Engineering]]></category>
		<category><![CDATA[cache]]></category>
		<category><![CDATA[rails]]></category>

		<guid isPermaLink="false">http://blog.agoragames.com/?p=246</guid>
		<description><![CDATA[Usually we use standard caching methods on our site (primarily fragment caching to avoid DB queries).
Occasionally we need to do something more fancy. These instances usually come up when we&#8217;re splitting one query into two because rails doesn&#8217;t support :force_index or :adapter_specific_find_options on ActiveRecord::Base.find. We understand this motivation but really hate ActiveRecord::Base.connection#find_by_sql or ActiveRecord::Base.connection#execute. These [...]]]></description>
			<content:encoded><![CDATA[<p>Usually we use standard caching methods on our site (primarily fragment caching to avoid DB queries).</p>
<p>Occasionally we need to do something more fancy. These instances usually come up when we&#8217;re splitting one query into two because rails doesn&#8217;t support :force_index or :adapter_specific_find_options on ActiveRecord::Base.find. We understand this motivation but really hate ActiveRecord::Base.connection#find_by_sql or ActiveRecord::Base.connection#execute. These are not rational hatreds.</p>
<p>So when we get into a situation where we&#8217;re going to be caching manually it&#8217;s usually in the controller and we almost always end up with a pattern of:</p>
<pre class="brush: ruby">
@object = Rails.cache.read(&#039;really/complicated/and/stinky/key&#039;)
if @object.nil?
@object = what_should_my_object_be?
end
</pre>
<p>That&#8217;s fine in a contrived example but we were doing this in about 10 different places and it looked like a good candidate for drying up.</p>
<p>Here&#8217;s the solution we use:</p>
<pre class="brush: ruby">
module ActiveSupport
module Cache
class Store
def read_and_write_if_nil(key, options = {})
object = read(key)
if object.nil?
object = yield
write(key, object, options)
end
object
end
end
end
end
</pre>
<p>And the production example looks like this:</p>
<pre class="brush: ruby">
account_ids = Rails.cache.read_and_write_if_nil(&quot;member_ids_for_clan_#{@clan.id}&quot;, :expires_in =&gt; 5.minutes) do
@clan.members.find(:all, :order =&gt; &#039;groupies DESC&#039;, :select =&gt; &#039;accounts.id&#039;).collect(&amp;amp;amp;:id)
end
</pre>




	<a rel="nofollow"  target="_blank" href="http://reddit.com/submit?url=http%3A%2F%2Fblog.agoragames.com%2F2009%2F05%2F13%2Fwrite-if-read-returns-nil%2F&amp;title=Write%20if%20read%20returns%20nil" title="Reddit"><img src="http://blog.agoragames.com/wp-content/plugins/var/www/waxer-blog/shared/wp-content/plugins/sociable/images/reddit.png" title="Reddit" alt="Reddit" class="sociable-hovers" /></a>
	<a rel="nofollow"  target="_blank" href="http://digg.com/submit?phase=2&amp;url=http%3A%2F%2Fblog.agoragames.com%2F2009%2F05%2F13%2Fwrite-if-read-returns-nil%2F&amp;title=Write%20if%20read%20returns%20nil&amp;bodytext=Usually%20we%20use%20standard%20caching%20methods%20on%20our%20site%20%28primarily%20fragment%20caching%20to%20avoid%20DB%20queries%29.%0D%0A%0D%0AOccasionally%20we%20need%20to%20do%20something%20more%20fancy.%20These%20instances%20usually%20come%20up%20when%20we%27re%20splitting%20one%20query%20into%20two%20because%20rails%20doesn%27t%20su" title="Digg"><img src="http://blog.agoragames.com/wp-content/plugins/var/www/waxer-blog/shared/wp-content/plugins/sociable/images/digg.png" title="Digg" alt="Digg" class="sociable-hovers" /></a>
	<a rel="nofollow"  target="_blank" href="http://delicious.com/post?url=http%3A%2F%2Fblog.agoragames.com%2F2009%2F05%2F13%2Fwrite-if-read-returns-nil%2F&amp;title=Write%20if%20read%20returns%20nil&amp;notes=Usually%20we%20use%20standard%20caching%20methods%20on%20our%20site%20%28primarily%20fragment%20caching%20to%20avoid%20DB%20queries%29.%0D%0A%0D%0AOccasionally%20we%20need%20to%20do%20something%20more%20fancy.%20These%20instances%20usually%20come%20up%20when%20we%27re%20splitting%20one%20query%20into%20two%20because%20rails%20doesn%27t%20su" title="del.icio.us"><img src="http://blog.agoragames.com/wp-content/plugins/var/www/waxer-blog/shared/wp-content/plugins/sociable/images/delicious.png" title="del.icio.us" alt="del.icio.us" class="sociable-hovers" /></a>
	<a rel="nofollow"  target="_blank" href="http://technorati.com/faves?add=http%3A%2F%2Fblog.agoragames.com%2F2009%2F05%2F13%2Fwrite-if-read-returns-nil%2F" title="Technorati"><img src="http://blog.agoragames.com/wp-content/plugins/var/www/waxer-blog/shared/wp-content/plugins/sociable/images/technorati.png" title="Technorati" alt="Technorati" class="sociable-hovers" /></a>


<br/><br/>]]></content:encoded>
			<wfw:commentRss>http://blog.agoragames.com/2009/05/13/write-if-read-returns-nil/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Porting Legacy Applications to Modern Systems</title>
		<link>http://blog.agoragames.com/2009/01/12/porting-legacy-applications-to-modern-systems/</link>
		<comments>http://blog.agoragames.com/2009/01/12/porting-legacy-applications-to-modern-systems/#comments</comments>
		<pubDate>Mon, 12 Jan 2009 17:58:36 +0000</pubDate>
		<dc:creator>Jason LaPorte</dc:creator>
				<category><![CDATA[Bending Rails]]></category>
		<category><![CDATA[Engineering]]></category>
		<category><![CDATA[attachment_fu]]></category>
		<category><![CDATA[file_column]]></category>
		<category><![CDATA[gettext]]></category>
		<category><![CDATA[legacy]]></category>
		<category><![CDATA[rails]]></category>

		<guid isPermaLink="false">http://blog.agoragames.com/?p=125</guid>
		<description><![CDATA[(Or, an adventure in pain!)
Let me preface this little article by saying I did not write the app I am now porting to our new network. I know noting about its specific intricacies, and furthermore, I know nothing specifically about gettext, file_column, or attachment_fu. So, I dove into this project with a sort of wanton [...]]]></description>
			<content:encoded><![CDATA[<p><em>(Or, an adventure in pain!)</em></p>
<p>Let me preface this little article by saying I did <strong>not</strong> write the app I am now porting to our new network. I know noting about its specific intricacies, and furthermore, I know nothing specifically about gettext, file_column, or attachment_fu. So, I dove into this project with a sort of wanton abandon that is fairly characteristic of much of the work I do. Any obviously stupid mistakes below thus really happened.</p>
<p>Let me also preface this with the fact that this Rails app is old. Version 1.2.3 old. So, as always, YMMV.</p>
<p>Finally, I really wish attachment_fu had proper documentation.</p>
<p><span id="more-125"></span></p>
<h2>Installing GetText 1.10.0</h2>
<p>We don&#8217;t really like GetText around here, but, at the time, it was the only option. Getting it running off of a local copy (so I wouldn&#8217;t have to pollute other projects with it) was less difficult than I expected. Go to your vendor/gems directory and issue:</p>
<pre>gem unpack gettext</pre>
<p>This assumes you have gettext 1.10.0 installed locally. I think adding a VERSION=1.10.0 will handle it if you have multiple gettext versions laying around. After that, I merely needed to add the following to config/environment.rb to make sure the gem loaded:</p>
<pre>GETTEXT_GEM_DIR = "#{File.expand_path(RAILS_ROOT)}/vendor/gems/gettext-1.10.0"
$LOAD_PATH.reject { |path| path =~ /gettext/ }
$LOAD_PATH &lt;&lt; GETTEXT_GEM_DIR
$LOAD_PATH &lt;&lt; File.join(GETTEXT_GEM_DIR, 'lib')
$LOAD_PATH &lt;&lt; File.join(GETTEXT_GEM_DIR, 'ext', 'gettext')
require File.join(GETTEXT_GEM_DIR, 'lib', 'gettext.rb')</pre>
<p>Ta-da!</p>
<h2>Replacing File_Column With Attachment_Fu</h2>
<p>After doing the above and booting up a test server, I get the following fun error:</p>
<pre>no such file to load -- RMagick</pre>
<p>There is no way I am ever installing RMagick onto our nice, new, beautiful infrastructure. I want things done right, here. I also don&#8217;t want to have to be paranoid about memory leaks, especially for legacy applications. So, we have to get rid of it.</p>
<p>This problem is caused by our use of file_column, an old-but-effective way of easily adding file uploading support into a Rails app. The modern <em>de facto</em> standard for this seems to be attachment_fu, which uses the much-better-designed ImageScience instead of RMagick.</p>
<p>So, let&#8217;s gut this fish.</p>
<h3>Remove File_Column.</h3>
<pre>$ svn rm vendor/plugins/file_column</pre>
<h3>Install ImageScience.</h3>
<pre>$ sudo apt-get -y install libfreeimage3 libfreeimage-dev
$ sudo gem install image_science</pre>
<h3>Install Attachment_Fu.</h3>
<pre>$ script/plugin install http://svn.techno-weenie.net/projects/plugins/attachment_fu/</pre>
<p>After installing attachment_fu, I powered back up script/server to check the next fun error:</p>
<pre>undefined method `file_column' for Clan:Class</pre>
<p>This is expected: file_column is gone, so the app can&#8217;t possibly know what a file_column is. Now, we have to get into the nitty-gritty of tweaking the app.</p>
<h3>Adapting the Application to Attachment_Fu.</h3>
<p>Let&#8217;s start in app/models/clan.rb, to which I was directed by the aforementioned error:</p>
<pre>$ grep file_column app/models/clan.rb</pre>
<p>No output. The words file_column don&#8217;t appear in that class. Not what I expected.</p>
<p>In the time-honored tradition of killing a cockroach with a shotgun, I then turned my sights on the entire app directory:</p>
<pre>$ grep -R file_column app</pre>
<p>The only results that turn up happen to be in app/views, leaving me perplexed. A quick conversation with the project lead informs me that this application uses &#8220;skeletons&#8221;, or appable_plugins, which was an absolutely horrible idea that we thankfully no longer use. In essence, it allows you to wrap pieces of functionality into a self-contained plugin, which is duck-punched onto your application when it starts. It is great from a code-reuse perspective, but horrible from a KISS and maintenance standpoint, which is why we no longer use it.</p>
<p>Except that every now and again, it comes back to bite you in the ass when you least expect it.</p>
<p>Anyway, checking the skeletons quickly turns up what I am looking for:</p>
<pre>$ grep -R file_column vendor/skeletons/clan_skeleton
vendor/skeletons/clan_skeleton/app/models/clan.rb:  file_column :avatar_image, :magick =&gt; { :size =&gt; "64x64!"}</pre>
<p>So, there is where I have to make the first incision. I changed it as follows:</p>
<pre># file_column :avatar_image, :magick =&gt; { :size =&gt; "64x64!"}
# validates_filesize_of :avatar_image, :in =&gt; 0..40.kilobytes

has_attachment :content_type =&gt; :image,
               :storage =&gt; :file_system,
               :max_size =&gt; 40.kilobytes,
               :resize_to =&gt; '64x64!'

validates_as_attachment</pre>
<p>Time to restart the server and try again. (I don&#8217;t honestly expect it to work: there are (at least!) a lot of views that use file_column methods. It is easiest to just hack at them one at a time until everything works, though!)</p>
<p>I spent the next couple hours digging through the innards of attachment_fu, only to discover that I had written :filesystem, above, instead of :file_system (note the underscore). Make sure you spell things correctly, people, or you&#8217;ll be in for a world of self-induced hurt. (The above snippet shows things the correct way, so you, my beloved internet, won&#8217;t inadvertently copy-and-paste yourself into hell.)</p>
<p>Once I had properly spelled everything, though, I met with success: the front page of the site loaded! Clicking on just about anything yielded a failure, as anticipated:</p>
<pre>undefined method `url_for_file_column' for #&lt;#&lt;Class:0x7f7d7f3006c0&gt;:0x7f7d7f300670&gt;</pre>
<p>The views didn&#8217;t work, but the fix wasn&#8217;t horrible. Generally speaking, I simply searched and replaced the following:</p>
<pre>url_for_file_column(X, 'avatar_image')</pre>
<p>with:</p>
<pre>X.public_filename</pre>
<p>Also, along with this, I modified the clan table&#8217;s SQL schema to accomodate attachment_fu:</p>
<pre>ALTER TABLE clans CHANGE avatar_image filename VARCHAR(255) DEFAULT NULL;
ALTER TABLE clans ADD (content_type VARCHAR(255) DEFAULT NULL,
                       size INT DEFAULT NULL,
                       width INT DEFAULT NULL,
                       height INT DEFAULT NULL);</pre>
<p>Thankfully, this was pretty easy to do, since the clans table was very small for this particular title. If it were larger, I would create a separate table and do a</p>
<pre>SELECT * FROM clans INSERT INTO clans_temp</pre>
<p>sort of thing. (Yes, I know that it is very evil to hack the SQL directly instead of using migrations. This app is sufficiently old that I cannot guarantee that its migrations even work; I&#8217;m already spending a lot of time trying to port this app, I don&#8217;t want to spend much more trying to make it perfect. If it weren&#8217;t a legacy application, however, I would do things a bit more cleanly.)</p>
<p>At this point, virtually everything on the site worked. Avatars (once moved to the proper new directories) showed up just fine. The only remaining error came from trying to upload a new avatar image. Solving this essentially boiled down to a complex series of hacks to blend attachment_fu into the remainder of the existing codebase; none of which were particularly complex or interesting (generally involving changing the names a form parameters from the previous :avatar_image to the new :uploaded_data, like this:)</p>
<pre>&lt;%#= file_column_field 'clan', 'avatar_image' %&gt;
&lt;%= file_field_tag :uploaded_data %&gt;</pre>
<p>Doing all this left me with one final application error, received when actually performing the file upload:</p>
<pre>Content type is not included in the list
content type can't be blank</pre>
<p>Validations are complaining. After tinkering with attachment_fu&#8217;s code for a while, I discover that there is a method that attachment_fu adds to your ActiveRecords (uploaded_data=), which sets content_type and other miscellaneous variables. And, clearly, this wasn&#8217;t getting called.</p>
<p>Turns out I was getting bitten by multipart forms. By tossing a quick</p>
<pre>puts params.inspect</pre>
<p>into the code, I quickly saw where my problem lay. Notice the following bit from our clans controller&#8217;s update method:</p>
<pre>@clan.update_attributes(params[:clan])</pre>
<p>Unfortunately for me, the uploaded data is in params[:uploaded_data], and not in params[:clan][:uploaded_data]. While there&#8217;s a cleaner fix, the following hack suits our purposes fine and allows me to finish up this 20-hour hackfest:</p>
<pre>params[:clan][:uploaded_data] = params[:uploaded_data]</pre>
<p>So, after all of this code mangling, we finally had our app ready to move to a new, lighter-weight infrastructure, ultimately saving us money. A very frustrating few days, but they will pay for themselves. All that remains is integrating into a new infrastructure, and switching over the DNS.</p>




	<a rel="nofollow"  target="_blank" href="http://reddit.com/submit?url=http%3A%2F%2Fblog.agoragames.com%2F2009%2F01%2F12%2Fporting-legacy-applications-to-modern-systems%2F&amp;title=Porting%20Legacy%20Applications%20to%20Modern%20Systems" title="Reddit"><img src="http://blog.agoragames.com/wp-content/plugins/var/www/waxer-blog/shared/wp-content/plugins/sociable/images/reddit.png" title="Reddit" alt="Reddit" class="sociable-hovers" /></a>
	<a rel="nofollow"  target="_blank" href="http://digg.com/submit?phase=2&amp;url=http%3A%2F%2Fblog.agoragames.com%2F2009%2F01%2F12%2Fporting-legacy-applications-to-modern-systems%2F&amp;title=Porting%20Legacy%20Applications%20to%20Modern%20Systems&amp;bodytext=%28Or%2C%20an%20adventure%20in%20pain%21%29%0D%0A%0D%0ALet%20me%20preface%20this%20little%20article%20by%20saying%20I%20did%20not%20write%20the%20app%20I%20am%20now%20porting%20to%20our%20new%20network.%20I%20know%20noting%20about%20its%20specific%20intricacies%2C%20and%20furthermore%2C%20I%20know%20nothing%20specifically%20about%20gettext%2C%20file_co" title="Digg"><img src="http://blog.agoragames.com/wp-content/plugins/var/www/waxer-blog/shared/wp-content/plugins/sociable/images/digg.png" title="Digg" alt="Digg" class="sociable-hovers" /></a>
	<a rel="nofollow"  target="_blank" href="http://delicious.com/post?url=http%3A%2F%2Fblog.agoragames.com%2F2009%2F01%2F12%2Fporting-legacy-applications-to-modern-systems%2F&amp;title=Porting%20Legacy%20Applications%20to%20Modern%20Systems&amp;notes=%28Or%2C%20an%20adventure%20in%20pain%21%29%0D%0A%0D%0ALet%20me%20preface%20this%20little%20article%20by%20saying%20I%20did%20not%20write%20the%20app%20I%20am%20now%20porting%20to%20our%20new%20network.%20I%20know%20noting%20about%20its%20specific%20intricacies%2C%20and%20furthermore%2C%20I%20know%20nothing%20specifically%20about%20gettext%2C%20file_co" title="del.icio.us"><img src="http://blog.agoragames.com/wp-content/plugins/var/www/waxer-blog/shared/wp-content/plugins/sociable/images/delicious.png" title="del.icio.us" alt="del.icio.us" class="sociable-hovers" /></a>
	<a rel="nofollow"  target="_blank" href="http://technorati.com/faves?add=http%3A%2F%2Fblog.agoragames.com%2F2009%2F01%2F12%2Fporting-legacy-applications-to-modern-systems%2F" title="Technorati"><img src="http://blog.agoragames.com/wp-content/plugins/var/www/waxer-blog/shared/wp-content/plugins/sociable/images/technorati.png" title="Technorati" alt="Technorati" class="sociable-hovers" /></a>


<br/><br/>]]></content:encoded>
			<wfw:commentRss>http://blog.agoragames.com/2009/01/12/porting-legacy-applications-to-modern-systems/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Those Pesky Memory Leaks</title>
		<link>http://blog.agoragames.com/2008/09/04/those-pesky-memory-leaks/</link>
		<comments>http://blog.agoragames.com/2008/09/04/those-pesky-memory-leaks/#comments</comments>
		<pubDate>Thu, 04 Sep 2008 13:36:52 +0000</pubDate>
		<dc:creator>Jason LaPorte</dc:creator>
				<category><![CDATA[Bending Rails]]></category>
		<category><![CDATA[Engineering]]></category>
		<category><![CDATA[maintenance]]></category>
		<category><![CDATA[memory leak]]></category>
		<category><![CDATA[rails]]></category>

		<guid isPermaLink="false">http://blog.agoragames.com/?p=51</guid>
		<description><![CDATA[First (technical) post!
AgoraGames has been doing community sites for several years now, which means that some of them are pretty old and some of them have particularly unruly codebases, especially one such site. This site (which shall remain nameless to protect the guilty) ran perfectly fine at launch, but over the course of a year-and-a-half [...]]]></description>
			<content:encoded><![CDATA[<p>First (technical) post!</p>
<p>AgoraGames has been doing community sites for several years now, which means that some of them are pretty old and some of them have particularly unruly codebases, especially one such site. This site (which shall remain nameless to protect the guilty) ran perfectly fine at launch, but over the course of a year-and-a-half has slowly gone from speed-demon to slug-stuck-in-molasses.</p>
<p><span id="more-51"></span></p>
<p><em>(I apologize for the lack of accompanying images, etc. as I worked through this&#8230; next time, I&#8217;ll keep posterity in mind as I work through an interesting problem!)</em></p>
<p>I&#8217;m the System Administrator here, so it&#8217;s my job to make sure that everything stays running smoothly from the OS&#8217;s standpoint; thanks to our religious use of <a href="http://www.tildeslash.com/monit/" target="_blank">monit</a>, the cause of the site&#8217;s slowness was pretty obvious: the mongrels running the site would balloon to consuming a gigabyte of memory within minutes, forcing monit to kill-and-restart the servers. This is a Bad Thing (TM).</p>
<p>Finding and fixing memory leaks in Rails isn&#8217;t the easiest task in the world (as other bloggers have been apt to mention), but in this case, the path to fixing it was pretty straightforward.</p>
<p>First task was to set up a separate bank of mongrels for the forums: since the site is so old, it&#8217;s the only part of the site that gets much traffic these days. I told NGINX to proxy all requests starting with /forums to those. It worked just fine, and the forums were immediately quite quick. From looking at monit, it was pretty apparent that the forum mongrels didn&#8217;t have the memory leak, since they ran without problems.</p>
<p>So, to start digging into the main portion of the site, I booted up a local server in production mode and <a href="http://curl.haxx.se/" target="_blank">curl</a>ed the homepage. It took a whopping 222 seconds (and, from looking at <a href="http://en.wikipedia.org/wiki/Top_(Unix)" target="_blank">top</a>, consumed 800MB of memory!). Looking at the debug logs, virtually all of that time was spend doing two queries: loading forum posts with associations, and loading tournaments with associations. Sounds a bit sketchy, no?</p>
<p>The home page&#8217;s controller was laid out very logically, so mapping the SQL queries in the log to method invokations in the controller was simple. There were two methods that were killing us, and they both looked something like this:</p>
<pre>class ForumPost &lt; ActiveRecord::Base
  ...
  def self.most_recent
    find(:first, :order =&gt; "forum_posts.created_at desc",
                 :include =&gt; [:account, :forum_topic, :forum])
  end
  ...
end</pre>
<p>Apparently, the find is loading up the (tens of thousands) of forum posts, <em>with all the associated objects!</em> Ruby doesn&#8217;t play nice when you have thousands of object in memory, and loading up hundreds of thousands of objects really makes things go south. Also makes sense why it didn&#8217;t become a problem for a while &#8212; it&#8217;s no big deal to load 100 object into memory (during testing and launch); but after a year and the site&#8217;s forum starts to fill&#8230;</p>
<p>But why? Isn&#8217;t this doing a :first? Shouldn&#8217;t it only be loading <em>one</em> object with associations? My guess is that Rails is loading all objects (with their associations) into an array and shifting off the first element. This isn&#8217;t smart behavior, but would explain what we&#8217;re seeing. (It&#8217;s also worth noting that this is using a fairly old version of Rails; I believe this silliness is fixed in more recent versions.)</p>
<p>Fixing this was actually trivial. Slap a :limit =&gt; 1 on there, or replace the :include with a :join. (Or, in the particular case above, remove the :include entirely. It&#8217;s not being used for anything relevant.)</p>
<p>I <a href="http://en.wikipedia.org/wiki/Grep" target="_blank">grep</a>ped the codebase for any other :includes, and fixed the ones that were broken. The site blazes along now and doesn&#8217;t leak, just like it did in its glory days.</p>
<p>Moral of the story: <strong>don&#8217;t use includes lightly</strong>. Make sure you know what your finds are actually doing. In our case, it translated into memory leaks, but it could just as easily translate into high database load, which is just as bad.</p>




	<a rel="nofollow"  target="_blank" href="http://reddit.com/submit?url=http%3A%2F%2Fblog.agoragames.com%2F2008%2F09%2F04%2Fthose-pesky-memory-leaks%2F&amp;title=Those%20Pesky%20Memory%20Leaks" title="Reddit"><img src="http://blog.agoragames.com/wp-content/plugins/var/www/waxer-blog/shared/wp-content/plugins/sociable/images/reddit.png" title="Reddit" alt="Reddit" class="sociable-hovers" /></a>
	<a rel="nofollow"  target="_blank" href="http://digg.com/submit?phase=2&amp;url=http%3A%2F%2Fblog.agoragames.com%2F2008%2F09%2F04%2Fthose-pesky-memory-leaks%2F&amp;title=Those%20Pesky%20Memory%20Leaks&amp;bodytext=First%20%28technical%29%20post%21%0D%0A%0D%0AAgoraGames%20has%20been%20doing%20community%20sites%20for%20several%20years%20now%2C%20which%20means%20that%20some%20of%20them%20are%20pretty%20old%20and%20some%20of%20them%20have%20particularly%20unruly%20codebases%2C%20especially%20one%20such%20site.%20This%20site%20%28which%20shall%20remain%20name" title="Digg"><img src="http://blog.agoragames.com/wp-content/plugins/var/www/waxer-blog/shared/wp-content/plugins/sociable/images/digg.png" title="Digg" alt="Digg" class="sociable-hovers" /></a>
	<a rel="nofollow"  target="_blank" href="http://delicious.com/post?url=http%3A%2F%2Fblog.agoragames.com%2F2008%2F09%2F04%2Fthose-pesky-memory-leaks%2F&amp;title=Those%20Pesky%20Memory%20Leaks&amp;notes=First%20%28technical%29%20post%21%0D%0A%0D%0AAgoraGames%20has%20been%20doing%20community%20sites%20for%20several%20years%20now%2C%20which%20means%20that%20some%20of%20them%20are%20pretty%20old%20and%20some%20of%20them%20have%20particularly%20unruly%20codebases%2C%20especially%20one%20such%20site.%20This%20site%20%28which%20shall%20remain%20name" title="del.icio.us"><img src="http://blog.agoragames.com/wp-content/plugins/var/www/waxer-blog/shared/wp-content/plugins/sociable/images/delicious.png" title="del.icio.us" alt="del.icio.us" class="sociable-hovers" /></a>
	<a rel="nofollow"  target="_blank" href="http://technorati.com/faves?add=http%3A%2F%2Fblog.agoragames.com%2F2008%2F09%2F04%2Fthose-pesky-memory-leaks%2F" title="Technorati"><img src="http://blog.agoragames.com/wp-content/plugins/var/www/waxer-blog/shared/wp-content/plugins/sociable/images/technorati.png" title="Technorati" alt="Technorati" class="sociable-hovers" /></a>


<br/><br/>]]></content:encoded>
			<wfw:commentRss>http://blog.agoragames.com/2008/09/04/those-pesky-memory-leaks/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>
<!-- WP Super Cache is installed but broken. The path to wp-cache-phase1.php in wp-content/advanced-cache.php must be fixed! -->