<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
 
 <title>LivingSocial Tech Team</title>
 <link href="http://tech.livingsocial.com/atom.xml" rel="self"/>
 <link href="http://tech.livingsocial.com/"/>
 <updated>2011-03-27T22:26:30+00:00</updated>
 <id>http://tech.livingsocial.com</id>
 <author>
   <name>LivingSocial Tech Team</name>
   <email>tech@livingsocial.com</email>
 </author>

 
 <entry>
   <title>JRuby "include?" 2x faster than 1.8.6?</title>
   <link href="http://tech.livingsocial.com/Ruby/2009/07/07/jruby-include-2x-faster-than-1-8-6.html"/>
   <updated>2009-07-07T00:00:00+00:00</updated>
   <id>http://tech.livingsocial.com/Ruby/2009/07/07/jruby-include-2x-faster-than-1-8-6</id>
   <content type="html">&lt;p&gt;Its been a few months since I’ve looked at JRuby and 1.8.6  can be annoying slow at simple things. So this morning I took another look at Ruby1.9 and JRuby.&lt;/p&gt;

&lt;p&gt;See gist below:&lt;br /&gt;
  &lt;script class=&quot;gist&quot; src=&quot;http://gist.github.com/142233.js&quot;&gt;&lt;/script&gt;
&lt;/p&gt;

&lt;p&gt;6.587s (1.8.6) vs. 5.687s (1.9) vs. 3.556s (JRuby 1.4)… and that’s just the include method. JRuby is almost 2x 1.8.6 without any optimizations.  I’ve read this this &lt;a href=&quot;http://blog.headius.com/2009/04/how-jruby-makes-ruby-fast.html&quot;&gt;awesome article&lt;/a&gt; about JRuby perf optimizations, but its unclear which flags are safe to run in a production environment beyond ‘–server’, which didn’t seem to impact local testing of a handful of iterations.&lt;/p&gt;

&lt;p&gt;Does anyone have Rails benchmarks running nightly comparing 1.8.6 against jruby?  I guess thats a more comprehensive test.&lt;/p&gt;

&lt;p&gt;UPDATE:  Eddie guessed PHP was much faster…  Apparently not.&lt;br /&gt;
  &lt;script class=&quot;gist&quot; src=&quot;http://gist.github.com/142262.js&quot;&gt;
  &lt;/script&gt;
&lt;/p&gt;

&lt;p&gt;UPDATE 2: Warren suggested a different method other than include, that would work. (a &amp;amp; [i]).empty? &lt;br /&gt;
  &lt;script class=&quot;gist&quot; src=&quot;http://gist.github.com/142269.js&quot;&gt;
  &lt;/script&gt;
&lt;/p&gt;

&lt;p&gt;Interesting to see it much faster on 1.8.6, consistent on JRuby, and slower on 1.9&lt;/p&gt;

&lt;p&gt;UPDATE 3 : Responses to comments from dmilith:  Sorry.The original gist had version numbers, if you look at its history. I put them back.  I do mention –server above, and even adding warmup to the script, it doesn't appear to impact numbers as all.  But for it to be warmed up, you’d have to run the benchmark 10k times? Whats an acceptable warmup period?  Also,  –fast seems strange to me.  Didn't help the numbers as well.&lt;/p&gt;

&lt;p&gt;I hate when people say uBenchmarks suck.  The ruby lang specs should include a suite of these types benchmarks as well.  Its important to keep tabs on them to help find route cause when macro performance suites improve/degrade over time.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Ruby Scoping Bug?</title>
   <link href="http://tech.livingsocial.com/Ruby/2009/01/28/ruby-scoping-bug.html"/>
   <updated>2009-01-28T00:00:00+00:00</updated>
   <id>http://tech.livingsocial.com/Ruby/2009/01/28/ruby-scoping-bug</id>
   <content type="html">&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Foo&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;title&lt;/span&gt;
&lt;span class=&quot;s2&quot;&gt;&amp;quot;Oh hai.&amp;quot;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;buggy&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;title&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;kp&quot;&gt;false&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;title&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;Oh noes!&amp;#39;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;title&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;no&quot;&gt;Foo&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;buggy&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;This code outputs:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;&lt;span class=&quot;no&quot;&gt;Oh&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;hai&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;
&lt;span class=&quot;kp&quot;&gt;nil&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Isn’t it odd that the variable being created in an if-false block is still being created and set to nil?  Hopefully this is fixed in Ruby 1.9.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Merb routing in Rails – Today!</title>
   <link href="http://tech.livingsocial.com/Rails/2008/12/29/merb-routing-in-rails.html"/>
   <updated>2008-12-29T00:00:00+00:00</updated>
   <id>http://tech.livingsocial.com/Rails/2008/12/29/merb-routing-in-rails</id>
   <content type="html">&lt;p&gt;We’ve been hearing great things about Merb routing so a few weeks ago, we wanted to see if we could get it working in a Rails application as a proof of concept. The goal of this project was to use the Merb routing engine along with router.rb and without touching any of our existing Rails application (i.e. anything in app/*). Pre-existing URL route recognition needed to continue to work and all named routes and url_for logic needed to generate the same URLs as before.&lt;/p&gt;

&lt;p&gt;With the &lt;a href=&quot;http://weblog.rubyonrails.org/2008/12/23/merb-gets-merged-into-rails-3&quot; target=&quot;_blank&quot;&gt;announcement that Merb and Rails are merging&lt;/a&gt;, we figured that it’d be a great time to share a little bit of what we learned.&lt;/p&gt;

&lt;h3&gt;Background&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;We’re running Rails 2.2.2&lt;/li&gt;
  &lt;li&gt;When we started messing with routes, we had 2500 generated routes (i.e. “rake routes | wc -l”).  After Aaron’s &lt;a href=&quot;http://rails.lighthouseapp.com/projects/8994/tickets/1359-add-optional-format-argument-to-named-routes&quot; target=&quot;_blank&quot;&gt;formatted routes patch&lt;/a&gt;, we had 1250.  We currently have over 1500.&lt;/li&gt;
  &lt;li&gt;Routing accounted for around 4 seconds out of 6 for ./script/console and mongrel_rails to start up.&lt;/li&gt;
  &lt;li&gt;Each mongrel_rails process was running at a minimum of 250mb in production.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;Step 1: compiling&lt;/h3&gt;

&lt;p&gt;Compiling is the first part of routing and involves loading an application’s routes.rb or router.rb and storing it in some way that allows for generation and recognition.&lt;/p&gt;

&lt;p&gt;The merb_routing plugin contains a subset of merb-core… just the classes related to routes.  It shouldn’t be a surprise that these classes assume they are running in a Merb environment and not a Rails environment.  To successfully load these merb routing classes without drastically modifying the source, we wrote two small compatibility layers (mini-merb and mini-extlib) that provide some basic functionality that Merb and ExtLib provide (i.e. Merb.logger, Merb.root, etc).  This enabled us to successfully load the Merb::Router classes in our environment without any errors.&lt;/p&gt;

&lt;p&gt;We then rewrote our routes.rb by hand using router.rb syntax.  We had to modify Merb routing slightly because we were getting “memory exhausted” compile errors.  It turned out that Merb routing uses a single if/elsif structure to recognize routes and due to our large number of routes, we hit a ruby quirk where you can’t have more than 2498 branches of logic in a single if-elsif statement.&lt;/p&gt;



&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;irb&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;&lt;span class=&quot;mo&quot;&gt;001&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;gt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;eval&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;if 1; &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;elsif 1;&amp;quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2498&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; end&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;=&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;gt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;kp&quot;&gt;nil&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;irb&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;&lt;span class=&quot;mo&quot;&gt;002&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;gt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;eval&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;if 1; &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;elsif 1;&amp;quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2499&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; end&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;no&quot;&gt;SyntaxError&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;eval&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:in&lt;/span&gt; &lt;span class=&quot;sb&quot;&gt;`irb_binding&amp;#39;: compile error&lt;/span&gt;
&lt;span class=&quot;sb&quot;&gt;(eval):1: memory exhausted&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;



&lt;p&gt;The quick fix was using many single if statement with a return inside rather than one giant if-elsif.    After a few hooks into ActionController::Routing we had our environment using Merb/router.rb instead of Rails/routes.rb.&lt;/p&gt;

&lt;p&gt;We had to make a few other minor changes to Merb routing to be compatible with rails:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;added support for { :method =&amp;gt; :any } in routing conditions&lt;/li&gt;
  &lt;li&gt;added support for BLAH_index as a named route for singular resources (Rails creates a named route called “blog_index” instead of just “blog” for singular resources)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Lastly, we wrote a rake task that overrides the default “rake routes” to pull from Merb routes instead of Rails routes.  At this point, we had the routes loaded and could see the objects in script/console.&lt;/p&gt;

&lt;h3&gt;Step 2: recognizing&lt;/h3&gt;

&lt;p&gt;Recognition is the second part of routing and happens at the beginning of every request.  It translates a URL into various parameters and figures out which controller/action to invoke for that request.&lt;/p&gt;

&lt;p&gt;Once we had router.rb working correctly, route recognition and parameter loading was surprisingly easy to wire in.&lt;/p&gt;

&lt;h3&gt;Step 3: generating&lt;/h3&gt;

&lt;p&gt;Generation is the third part of routing and translates structured options into a URL string.  This happens every time you use url_for, a named route helper or redirect_to.&lt;/p&gt;

&lt;p&gt;Generation was the trickiest part of this project and had the most edge cases.  Philosophically speaking, Merb and Rails route generation are very different.  Rails gives you named routes as helpers (person_path, person_url, etc) that you can use as well as a url_for() method which will search through all of the routes and find the best route given the options you provide.  Merb on the other hand provides a single method, url(), which all generation goes through.  If you don’t explicitly provide a named route, url() will use the default route (i.e. :controller/:action/:id) rather than looking for the “best route”.&lt;/p&gt;

&lt;p&gt;Getting the named routes to work was pretty easy and only required a single method_missing catch-all for ActionController::Base and ActionView::Base.  Using a simple regexp, if the requested method ends in _url or _path, it uses Merb::Router#url and passes in the named route.&lt;/p&gt;

&lt;p&gt;There was a bit of trickery involved in getting the path vs. url as well as the  :only_path stuff working correctly, but overall not too hard.&lt;/p&gt;

&lt;p&gt;The last tricky piece was returning the best route instead of the default route when no named route was provided.  This is accomplished by looping through all of the available routes and determining which of the routes satisfies the most options passed in.  With 1500 routes, this turned out to be a bit slow, so some optimization ideas were borrowed from Rails and a cache is maintained of available routes given a controller/action.&lt;/p&gt;

&lt;h3&gt;Conclusion&lt;/h3&gt;

&lt;p&gt;We’ve been using this plugin successfully in production for the last month.  Our environment startup time as well as our memory overhead were both reduced drastically as soon as we put it in to production. We started this development when Rails 2.1 was the latest stable release and benchmarks against Rails 2.1 put Merb routing way ahead in just about every metric we tested.
&lt;/p&gt;

&lt;p&gt;The routing in Rails 2.2 was sped up substantially and is now comparable to Merb (Rails wins in some benchmarks, Merb in others).&lt;strong&gt;BUT…. Merb still blows away rails in startup time, by 2-3x.&lt;/strong&gt;We thought we could take out our merb-routing hacks and reduce pre complexity, but after watching production restarts, we decided to put it back.&lt;/p&gt;

&lt;p&gt;This plugin can be found on github: &lt;a style=&quot;text-decoration: none;&quot;  href=&quot;http://github.com/hungrymachine/merb_routing/tree/master&quot; target=&quot;_blank&quot;&gt;merb_routing&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;UPDATE: after talking to Carl Lerche, it sounds like the new router refactoring he is working on will support both syntaxes on the same prebase. That’ll be very cool.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Modular routing in rails and merb (acts_as_routing)</title>
   <link href="http://tech.livingsocial.com/Rails/2008/11/26/acts_as_routing-modular-routing-in-rails-and-merb.html"/>
   <updated>2008-11-26T00:00:00+00:00</updated>
   <id>http://tech.livingsocial.com/Rails/2008/11/26/acts_as_routing-modular-routing-in-rails-and-merb</id>
   <content type="html">&lt;p&gt;Here’s a proof of concept plugin that will monkeypatch Rails or Merb routing to allow you to define “acts as blocks” anywhere throughout your application (i.e. a plugin) and then use them in your routes file.&lt;/p&gt;

&lt;p&gt;Imagine the plugin acts_as_commentable defines the following in its init.rb:&lt;/p&gt;

&lt;pre class=&quot;code&quot;&gt;
&lt;span class=&quot;bluecode&quot; style=&quot;color:#036; font-weight:bold&quot;&gt;ActionController::Routing&lt;/span&gt;.routes_for_acts_as(&lt;span style=&quot;color:#A60&quot;&gt;:commentable&lt;/span&gt;) &lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;do&lt;/span&gt; |map|
  map.resources &lt;span style=&quot;color:#A60&quot;&gt;:comments&lt;/span&gt;
  map.best_comment &lt;span style=&quot;background-color:#fff0f0&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;'&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;/best-comment&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;'&lt;/span&gt;&lt;/span&gt;, &lt;span style=&quot;color:#A60&quot;&gt;:controller&lt;/span&gt; =&amp;gt; &lt;span style=&quot;background-color:#fff0f0&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;'&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;comments&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;'&lt;/span&gt;&lt;/span&gt;, &lt;span style=&quot;color:#A60&quot;&gt;:action&lt;/span&gt; =&amp;gt; &lt;span style=&quot;background-color:#fff0f0&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;'&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;best&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;'&lt;/span&gt;&lt;/span&gt;
&lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;end&lt;/span&gt;&lt;/pre&gt;

&lt;p&gt;If you added these :acts_as to your config/routes.rb:&lt;/p&gt;

&lt;pre class=&quot;code&quot;&gt;
&lt;span style=&quot;color:#036; font-weight:bold&quot;&gt;ActionController&lt;/span&gt;::&lt;span style=&quot;color:#036; font-weight:bold&quot;&gt;Routing&lt;/span&gt;::&lt;span style=&quot;color:#036; font-weight:bold&quot;&gt;Routes&lt;/span&gt;.draw &lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;do&lt;/span&gt; |map|

  map.resources &lt;span style=&quot;color:#A60&quot;&gt;:people&lt;/span&gt;, &lt;span style=&quot;color:#A60&quot;&gt;:acts_as&lt;/span&gt; =&amp;gt; [&lt;span style=&quot;color:#A60&quot;&gt;:commentable&lt;/span&gt;]

  map.resources &lt;span style=&quot;color:#A60&quot;&gt;:posts&lt;/span&gt;, &lt;span style=&quot;color:#A60&quot;&gt;:acts_as&lt;/span&gt; =&amp;gt; [&lt;span style=&quot;color:#A60&quot;&gt;:commentable&lt;/span&gt;]

&lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;end&lt;/span&gt;&lt;/pre&gt;

&lt;p&gt;You could then use these routes throughout your application:&lt;/p&gt;

&lt;pre class=&quot;code&quot;&gt;  &amp;lt;%=person_comments_path(&lt;span style=&quot;color:#036; font-weight:bold&quot;&gt;Person&lt;/span&gt;.first)%&amp;gt;

  &amp;lt;%=post_comments_path(&lt;span style=&quot;color:#036; font-weight:bold&quot;&gt;Post&lt;/span&gt;.first)%&amp;gt;

  &amp;lt;%=person_best_comment_path(&lt;span style=&quot;color:#036; font-weight:bold&quot;&gt;Person&lt;/span&gt;.first)%&amp;gt;&lt;/pre&gt;


&lt;p&gt;This is equivalent to doing:&lt;/p&gt;

&lt;pre class=&quot;code&quot;&gt;
&lt;span style=&quot;color:#036; font-weight:bold&quot;&gt;ActionController&lt;/span&gt;::&lt;span style=&quot;color:#036; font-weight:bold&quot;&gt;Routing&lt;/span&gt;::&lt;span style=&quot;color:#036; font-weight:bold&quot;&gt;Routes&lt;/span&gt;.draw &lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;do&lt;/span&gt; |map|

  map.resources &lt;span style=&quot;color:#A60&quot;&gt;:people&lt;/span&gt; &lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;do&lt;/span&gt; |people_map|
    people_map.resources &lt;span style=&quot;color:#A60&quot;&gt;:comments&lt;/span&gt;

    people_map.best_comment &lt;span style=&quot;background-color:#fff0f0&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;'&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;/best-comment&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;'&lt;/span&gt;&lt;/span&gt;, &lt;span style=&quot;color:#A60&quot;&gt;:controller&lt;/span&gt; =&amp;gt; &lt;span style=&quot;background-color:#fff0f0&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;'&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;comments&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;'&lt;/span&gt;&lt;/span&gt;, &lt;span style=&quot;color:#A60&quot;&gt;:action&lt;/span&gt; =&amp;gt; &lt;span style=&quot;background-color:#fff0f0&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;'&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;best&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;'&lt;/span&gt;&lt;/span&gt;

  &lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;end&lt;/span&gt;

  map.resources &lt;span style=&quot;color:#A60&quot;&gt;:posts&lt;/span&gt; &lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;do&lt;/span&gt; |posts_map|

    posts_map.resources &lt;span style=&quot;color:#A60&quot;&gt;:comments&lt;/span&gt;

    posts_map.best_comment &lt;span style=&quot;background-color:#fff0f0&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;'&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;/best-comment&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;'&lt;/span&gt;&lt;/span&gt;, &lt;span style=&quot;color:#A60&quot;&gt;:controller&lt;/span&gt; =&amp;gt; &lt;span style=&quot;background-color:#fff0f0&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;'&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;comments&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;'&lt;/span&gt;&lt;/span&gt;, &lt;span style=&quot;color:#A60&quot;&gt;:action&lt;/span&gt; =&amp;gt; &lt;span style=&quot;background-color:#fff0f0&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;'&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;best&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;'&lt;/span&gt;&lt;/span&gt;

  &lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;end&lt;/span&gt;

&lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;end&lt;/span&gt;&lt;/pre&gt;

&lt;p&gt;The plugin is available on github: &lt;a href=&quot;http://github.com/hungrymachine/acts_as_routing/tree/master%20&quot;&gt;http://github.com/hungrymachine/acts_as_routing/tree/master&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;P.S. At some point, I’ll submit patches to Rails and Merb so this functionality is native rather than provided via a monkeypatching plugin.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>JRuby and why it might be nice to be back on the JVM – Part 2</title>
   <link href="http://tech.livingsocial.com/Ruby/2008/11/21/jruby-and-why-it-might-be-nice-to-be-back-on-the-jvm-part-2.html"/>
   <updated>2008-11-21T00:00:00+00:00</updated>
   <id>http://tech.livingsocial.com/Ruby/2008/11/21/jruby-and-why-it-might-be-nice-to-be-back-on-the-jvm-part-2</id>
   <content type="html">&lt;p&gt;In the previous post, I did some &lt;a href=&quot;http://blog.hungrymachine.com/2008/11/19/jruby-and-why-it-might-be-nice-to-be-back-on-the-jvm&quot;&gt;JRuby testing&lt;/a&gt;
and noticed perf improvements over time.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://www.workingwithrails.com/person/6010-mark-imbriaco&quot;&gt;Mark Imbriaco&lt;/a&gt;, of 37Signals, asked how it compared to MRI. I was curious too.&lt;/p&gt;

&lt;p&gt;I can’t promise a “clean” comparison, your mileage may vary, but… MRI was:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text&quot;&gt;Completed in 552ms (View: 104, DB: 14) | 200 OK [http://someurl.com/people/3]
Completed in 345ms (View: 60, DB: 3) | 200 OK [http://someurl.com/people/3]
Completed in 346ms (View: 60, DB: 4) | 200 OK [http://someurl.com/people/3]
Completed in 347ms (View: 56, DB: 4) | 200 OK [http://someurl.com/people/3]
Completed in 349ms (View: 58, DB: 5) | 200 OK [http://someurl.com/people/3]
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p class=&quot;text&quot;&gt;Some stats on my runtime&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;java&quot;&gt;&lt;span class=&quot;n&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;java&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;version&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;java&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;version&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;1.5.0_16&amp;quot;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;Java&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;TM&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Runtime&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Environment&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Standard&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Edition&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;build&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;1.5&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_16&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b06&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;284&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;Java&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;HotSpot&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;TM&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Client&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;VM&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;build&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;1.5&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_16&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;133&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mixed&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mode&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sharing&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ruby&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;ruby&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;1.8&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2008&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;08&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;11&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;patchlevel&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;287&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i686&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;darwin9&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;5.0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Both ran on a MacBook 2.53GHz.  Likely the perf is better on Java6?&lt;/p&gt;

&lt;p&gt;Installed &lt;a href=&quot;http://support.apple.com/downloads/Java_for_Mac_OS_X_10_5_Update_1&quot;&gt;Java6&lt;/a&gt; and re-ran. Similar but better results.&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text&quot;&gt;Completed in 8815ms (View: 1632, DB: 429) | 200 OK [http://someurl.com/people/3]
Completed in 1017ms (View: 656, DB: 25) | 200 OK [http://someurl.com/people/3]
Completed in 998ms (View: 618, DB: 18) | 200 OK [http://someurl.com/people/3]
Completed in 1300ms (View: 437, DB: 35) | 200 OK [http://someurl.com/people/3]
Completed in 315ms (View: 119, DB: 21) | 200 OK [http://someurl.com/people/3]
Completed in 361ms (View: 140, DB: 20) | 200 OK [http://someurl.com/people/3]
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Wow! Thats damn close to MRI…eventually… JRuby warmup time sucks though. Maybe warm it up during deploy before putting it back into the load balancer?  Not exactly sure how to warm it correctly though.  &lt;/p&gt;

&lt;p&gt;If you just hit a URL on your app, you’ll only warm up THAT execution path… and you cant hit all actions, so…. thoughts?&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>JRuby and why it might be nice to be back on the JVM</title>
   <link href="http://tech.livingsocial.com/Ruby/2008/11/19/jruby-and-why-it-might-be-nice-to-be-back-on-the-jvm.html"/>
   <updated>2008-11-19T00:00:00+00:00</updated>
   <id>http://tech.livingsocial.com/Ruby/2008/11/19/jruby-and-why-it-might-be-nice-to-be-back-on-the-jvm</id>
   <content type="html">&lt;p&gt;We ported our Rails application to JRuby in order to do some GC comparisons yesterday.  Not a ton of changes required. Mostly replacing gems with native dependencies. YAML is a bit more strict than its MRI counterpart…. but all told, thats pretty amazing!  Nice job JRuby crew!&lt;/p&gt;

&lt;p&gt;That said…. one interesting, entirely un-scientific, test case.  After requesting the same URL 6 times, the VM got a lot better. 3.4s to 480ms&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text&quot;&gt;Completed in 3380ms (View: 2739, DB: 65) | 200 OK [http://someurl.com/people/3]
Completed in 1299ms (View: 1211, DB: 18) | 200 OK [http://someurl.com/people/3]
Completed in 1020ms (View: 949, DB: 20) | 200 OK [http://someurl.com/people/3]
Completed in 852ms (View: 732, DB: 18) | 200 OK [http://someurl.com/people/3]
Completed in 743ms (View: 628, DB: 31) | 200 OK [http://someurl.com/people/3]
Completed in 485ms (View: 374, DB: 14) | 200 OK [http://someurl.com/people/3]
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;It doesnt appear to be the DB caching the data. That time stayed consistent.&lt;/p&gt;
&lt;p&gt; I didnt use any crazy runtime flags.. Just jetty, a war file, and -server…. &lt;/p&gt;
&lt;p&gt;If it was something we were memcaching, then after the 2nd request, it would have been consistent. &lt;/p&gt;
&lt;p&gt;The amount of time spent in the view improved dramatically. &lt;/p&gt;
&lt;p&gt;I didnt think JRuby leveraged JIT’ing yet.  Anyone care to guess/explain why it was significantly better per request?&lt;/p&gt;
&lt;p&gt;Note: It did trail off in the 300ms range with further testing...&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Are your mongrels growing by 20MB/request on Rails 2.2? Blame AssetTag!</title>
   <link href="http://tech.livingsocial.com/Rails/2008/11/19/are-your-mongrels-growing-to-600mb-blame-assettag.html"/>
   <updated>2008-11-19T00:00:00+00:00</updated>
   <id>http://tech.livingsocial.com/Rails/2008/11/19/are-your-mongrels-growing-to-600mb-blame-assettag</id>
   <content type="html">&lt;p&gt;After porting our production application to Rails 2.2, we noticed a major memory leak.&lt;/p&gt;

&lt;p&gt;Beforehand, monit would restart instances a handful of times a day.  After Rails 2.2, monit restarted instances THOUSANDS of times a day.&lt;/p&gt;

&lt;p&gt;This is a graph of one of our haproxy instances a couple days ago.&lt;/p&gt;

&lt;p&gt;&lt;img class=&quot;image&quot; src=&quot;http://blog.hungrymachine.com/assets/2008/11/19/Picture_79.png&quot; style=&quot;padding:10px;width:680px&quot;&gt;&lt;/p&gt;

&lt;p&gt;We looked at everything, including time spent &lt;a href=&quot;http://blog.hungrymachine.com/2008/11/8/how-to-save-100m-of-ram-per-mongrel&quot;&gt;rewriting&lt;/a&gt; &lt;a href=&quot;http://blog.hungrymachine.com/2008/11/11/how-to-save-100m-of-ram-per-mongrel-part-2&quot;&gt;Routes&lt;/a&gt;, thinking that was the culprit. &lt;/p&gt;

&lt;p&gt;This morning, we all sat around and fought the issue old school style. binary debugging… and found it: AssetTagHelper. See the patch &lt;a href=&quot;http://rails.lighthouseapp.com/projects/8994-ruby-on-rails/tickets/1419-massive-memory-leak-in-assettag&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The new thread-safe asset tag code keeps a static AssetTag::Cache = {}  of all asset_tags created (css,jss, and all images).&lt;/p&gt;

&lt;p&gt;Internally, each AssetTag object keeps a reference to the controller and template objects, and in turn all instance variables you created in your request.  &lt;/p&gt;

&lt;p&gt;What does that mean?  Say you have a people controller, that loads a person and their stuff, and you show images of their stuff via image_tag().&lt;/p&gt;


&lt;pre class=&quot;code&quot;&gt;
 class PeopleController  30)
   end
 end
&lt;/pre&gt;

&lt;p&gt; When image_tag() is called, it does rails magic to append file extensions, asset_ids, and the like.  To be smart, it caches those objects so it doesnt hit the file system&lt;br&gt;
to figure all that out on every request.  The problem is it puts it in a static cache, AssetTag::Cache.&lt;/p&gt;

&lt;p&gt; So each PeopleController instance has a reference to 1 person and 30 Stuffs.  After 1000 people look at their pages, or better yet google crawls your site, you have 1k @controllers with a total of 1000 People Objects, and 1000*30 Stuff objects.  This would normally be fine.  The objects leave scope and get GC’ed. But, if you generate an image tag to an unique asset, AssetTag puts that into a cache, AssetTag::Cache, with a reference to the @controller of the request.  So All People and their Stuff are kept around forever, unable to be GC’ed…. every time a unique image is rendered via AssetTag. Eventually monit has to kill the process.&lt;/p&gt;

&lt;p&gt;The &lt;a href=&quot;http://rails.lighthouseapp.com/projects/8994-ruby-on-rails/tickets/1419-massive-memory-leak-in-assettag&quot;&gt;patch&lt;/a&gt; we just submitted does 2 things.&lt;/p&gt;

&lt;p&gt; 1) It now keeps a cache of just the modified path strings, caching the file access stuff.  If you have tons of local images, reference them by fully qualified host. Thats better for lots of reasons. Cookie-less asset hosts with multiple subdomains FTW!&lt;/p&gt;

&lt;p&gt; 2) It stops caching absolute URL paths. You cant do anything on the filesystem to verify them, and keeping a cache of those would also grow unbounded. We have millions of items in our system, each with a reference to an image.&lt;/p&gt;

&lt;p&gt;Here is a graph of that haproxy today…  Sleeping………&lt;/p&gt;

&lt;p&gt;&lt;img class=&quot;image&quot; src=&quot;http://blog.hungrymachine.com/assets/2008/11/19/Picture_80.png&quot; style=&quot;padding:10px;width:680px&quot;&gt;&lt;/p&gt;

&lt;p&gt;In order to do some testing of your own, here’s a simplistic after_filter you can add to application.rb (or is it now application_controller.rb?). Make sure you run this in production mode or with cache_classes = true.  As you click around your site, you should see that the cache retains references to controller instances, just to name a few.  After you apply the patch, you’ll see the cache is just strings.&lt;/p&gt;


&lt;pre class=&quot;code&quot;&gt;
 def assettag_cache
    puts &quot;-&quot;*80
    puts &quot;[AssetTag::Cache] Now #{ActionView::Helpers::AssetTagHelper::AssetTag::Cache.size} items&quot;
    ActionView::Helpers::AssetTagHelper::AssetTag::Cache.values.each do |asset_tag|
      if asset_tag === ActionView::Helpers::AssetTagHelper::AssetTag
        puts &quot;   [Asset] #{asset_tag.instance_variable_get(&quot;@source&quot;)}  #{asset_tag.instance_variable_get(&quot;@controller&quot;).class.to_s}&quot;
      else
        puts &quot;   [Asset] #{asset_tag}&quot;
      end
    end
  end
&lt;/pre&gt;

&lt;p&gt;Ohh… and we havent given up on routes… Warren is working on some very interesting enhancements to rails routing.  Looking forward to blogging about that soon.&lt;/p&gt;

</content>
 </entry>
 
 <entry>
   <title>How to save 100m of RAM per mongrel (Part 2)</title>
   <link href="http://tech.livingsocial.com/Performance/2008/11/11/how-to-save-100m-of-ram-per-mongrel-part-2.html"/>
   <updated>2008-11-11T00:00:00+00:00</updated>
   <id>http://tech.livingsocial.com/Performance/2008/11/11/how-to-save-100m-of-ram-per-mongrel-part-2</id>
   <content type="html">&lt;p&gt;&lt;strong&gt;UPDATE&lt;/strong&gt; I’ve added a patch to Rails Edge for this fix, which is much different than the patch below.  See &lt;a href=&quot;http://rails.lighthouseapp.com/projects/8994-ruby-on-rails/tickets/1359-add-optional-format-argument-to-named-routes#ticket-1359-5&quot;&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In a &lt;a href=&quot;http://blog.hungrymachine.com/2008/11/8/how-to-save-100m-of-ram-per-mongrel&quot;&gt;previous article&lt;/a&gt;, I called out the massive memory usage of the default rails resource behavior, and it seems &lt;a href=&quot;http://rails.lighthouseapp.com/projects/8994/tickets/1215-add-actions-and-formatted-options-to-mapresources#ticket-1215-18&quot;&gt;others&lt;/a&gt; have as well.  In an attempt to decrease the number of routes, I commented out the “formatted_*” routes, and manually entered them back by hand.&lt;/p&gt;

&lt;p&gt;But after some internal discussion/testing with Warren, we realized that was sloppy and error prone.  Instead, I hacked Routing segments to allow for an optional format segment, so that formatted routes and normal routes are shared.  The one downside, from what I can tell so far, is you lose “formatted_*” named routes + url helpers for those routes, but passing format to a url_for still works&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;person_path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:id&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:format&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;json&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;  &lt;span class=&quot;sr&quot;&gt;/people/&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;json&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;In the below gist, you’ll see a OptionalFormatSegment, which sneakily gets around the ‘.’ regex separator, removes the formatted_* named routes added by default, and should be the same solution as the previous post, but without the need to manually put all the routes back in.  &lt;/p&gt;

&lt;p&gt;&lt;script class=&quot;gist&quot;&gt; src=&quot;http://gist.github.com/23712.js&quot;&gt;&lt;/script&gt;&lt;/p&gt;

&lt;p&gt;I’m still testing this approach, but am interested in what other folks think.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; This monkey-patch only works on Rails 2.2&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>How to save 100m of RAM per mongrel</title>
   <link href="http://tech.livingsocial.com/Performance/2008/11/08/how-to-save-100m-of-ram-per-mongrel.html"/>
   <updated>2008-11-08T00:00:00+00:00</updated>
   <id>http://tech.livingsocial.com/Performance/2008/11/08/how-to-save-100m-of-ram-per-mongrel</id>
   <content type="html">&lt;p&gt;&lt;strong&gt;UPDATE:&lt;/strong&gt; See  &lt;a href=&quot;http://blog.hungrymachine.com/2008/11/11/how-to-save-100m-of-ram-per-mongrel-part-2&quot;&gt;Part 2&lt;/a&gt; of this for a better solution&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; This monkey-patch only works on Rails 2.2&lt;/p&gt;

&lt;p&gt;We recently noticed our mongrels, upon startup, were 244M.  Eek. &lt;/p&gt;

&lt;pre class=&quot;code&quot;&gt;
PID USER            PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
53749 some_user     15   0  337m 244m 2912 S    0  2.0   0:17.49 mongrel_rails
&lt;/pre&gt;

&lt;p&gt;Running &lt;a href=&quot;http://blog.evanweaver.com/files/doc/fauna/bleak_house/files/README.html&quot;&gt;Bleakhouse&lt;/a&gt; on our rails app, i was amazed at the number of objects created.  over 2M!&lt;/p&gt;

&lt;pre class=&quot;code&quot;&gt;
$ BLEAK_HOUSE=1 ruby-bleak-house ./script/runner 'puts 1'
** Bleakhouse: installed
1
** BleakHouse: working...
** BleakHouse: complete
** Bleakhouse: Run 'bleak /tmp/bleak.53749.0.dump' to analyze.

$ bleak /tmp/bleak.53749.0.dump
Displaying top 20 most common line/class pairs
2,047,025 total objects
2,047,025 filled heap slots
2,403,764 free heap slots
1779063 __null__:__null__:__node__
197423 __null__:__null__:String
16519 __null__:__null__:Array
12728 __null__:__null__:ActionController::Routing::DividerSegment
10495 __null__:__null__:Hash
5676 __null__:__null__:ActionController::Routing::StaticSegment
5436 __null__:__null__:Class
5132 __null__:__null__:Regexp
4525 __null__:__null__:ActionController::Routing::DynamicSegment
2524 __null__:__null__:ActionController::Routing::Route
1307 __null__:__null__:Gem::Version
&lt;/pre&gt;

&lt;p&gt;Whats up with all those routing objects! So i tried a blank routes.rb file….&lt;/p&gt;

&lt;pre class=&quot;code&quot;&gt;
519,307 total objects
519,307 filled heap slots
233,503 free heap slots
&lt;/pre&gt;

&lt;p&gt;Arghh….  1.5M objects just because of routes.rb. I know our application is large, lots of resources and nested resources, but thats crazy.  &lt;/p&gt;

&lt;pre class=&quot;code&quot;&gt;
$ rake routes | wc -l
2516
&lt;/pre&gt;

&lt;p&gt;Ok, so taking a closer look, I realized something. Each resource route has a corresponding formatted_* route, lots of which we dont use. So now for some nasty monkey-patching.&lt;/p&gt;

&lt;pre class=&quot;code&quot;&gt;
ActionController::Routing::RouteSet::Mapper.class_eval do
protected

  def map_unnamed_routes(map, path_without_format, options)
    map.connect(path_without_format, options)
    #map.connect(&quot;#{path_without_format}.:format&quot;, options)
  end

  def map_named_routes(map, name, path_without_format, options)
    map.named_route(name, path_without_format, options)
    #map.named_route(&quot;formatted_#{name}&quot;, &quot;#{path_without_format}.:format&quot;, options)
  end
end
&lt;/pre&gt;

&lt;p&gt;I then manually added back the formatted routes we needed, careful to use named routes as “map.formatted_foo_bar”&lt;/p&gt;

&lt;pre class=&quot;code&quot;&gt;
$ rake routes | wc -l
1490

$ bleak /tmp/bleak.56554.0.dump
1,242,796 total objects
1,242,796 filled heap slots
1,224,309 free heap slots
&lt;/pre&gt;

&lt;p&gt;Awesome.  I no longer create almost 800k objects. &lt;/p&gt;

&lt;pre class=&quot;code&quot;&gt;
PID USER            PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
56554 someuser     15   0  249m 156m 2912 S    0  1.3   0:09.92 mongrel_rails
&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;244m&lt;/strong&gt; &amp;gt; &lt;strong&gt;156m&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This is not a very elegant solution… but I saved almost 100m per mongrel. Ohh.. and it reduced startup time by 50%.&lt;/p&gt;

&lt;p&gt;How big are your mongrels?&lt;/p&gt;

&lt;p&gt;How does Merb’s router differ from Rails routing? Worth investigating?&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>MRI Ruby + MySQL + Threads == Stop the world… JRuby doesn’t</title>
   <link href="http://tech.livingsocial.com/Ruby/2008/08/27/ruby-and-multi-threaded-mysql-mri-vs-jruby-jdbc-vs-dataobjects-mysql.html"/>
   <updated>2008-08-27T00:00:00+00:00</updated>
   <id>http://tech.livingsocial.com/Ruby/2008/08/27/ruby-and-multi-threaded-mysql-mri-vs-jruby-jdbc-vs-dataobjects-mysql</id>
   <content type="html">&lt;div class=&quot;text&quot;&gt;
          &lt;p&gt;As we have been internally discussing how to scale our databases from 10’s of millions of rows to 100’s of millions, database sharding came up.  &lt;/p&gt;
&lt;p&gt;Depending on your data model and your application, sharding data into tables by some natural key is great if any given request uses only one shard. FiveRun’s &lt;a href=&quot;http://blog.fiveruns.com/2008/7/9/introducing-data_fabric&quot;&gt;DataFabric&lt;/a&gt; seems to help with that.  Its obviously best to shard the data in the most used way, but occasionally you’ll need to write broadcast queries across shards.  It’d be even better if those broadcast queries were executed concurrently. Well, apparently, its not that simple in MRI Ruby.&lt;/p&gt;
&lt;p&gt;The mysql (2.7) gem stop’s the world while executing a query. A sloppy but reproducible test is &lt;a href=&quot;http://pastie.org/248044&quot;&gt;here&lt;/a&gt;.  This is not a mutex lock on the re-use of a single connection object.  Eddie also reached out to the &lt;a href=&quot;http://sequel.rubyforge.org/&quot;&gt;Sequel&lt;/a&gt; maintainer, who agrees it is likely due “to the fact that the C drivers don’t release the interpreter lock while they wait for a response from the server.” JRuby, or more accurately JDBC, acts as expected.  We even tested &lt;a href=&quot;http://datamapper.org/&quot;&gt;DataMapper&lt;/a&gt;’s DataObjects::MySQL, as it appears they’ve re-implemented the mysql gem.   Unfortunately it suffers from the same stop-the-world issue.  &lt;/p&gt;
&lt;pre class=&quot;code&quot;&gt;
$ ruby mysql_locking_test.rb
Loading MRI MySQL
Serial: 4.00969815254211s
Multi-threaded: 4.00785183906555s

$ data_mapper=true ruby mysql_locking_test.rb
Loading DataMapper
Serial: 4.01330804824829s
Multi-threaded: 4.01132893562317s

$ jruby mysql_locking_test.rb
Loading JDBC-MySQL
Serial: 4.2802369594573975s
Multi-threaded: 1.0499329566955566s
&lt;/pre&gt;
&lt;p&gt;Only in JRuby was the multi-threaded != sequential time, as expected. &lt;/p&gt;
&lt;p&gt;Potentially unrelated, no one has touched the mysql gem in 3 years?!?!  &lt;/p&gt;
&lt;pre class=&quot;code&quot;&gt;
$ gem spec -v 2.7 mysql | grep date
date: 2005-10-09 00:00:00 +00:00
&lt;/pre&gt;
&lt;p&gt;So even Ruby ORM frameworks (Sequel, DataMapper) that say they’re thread-safe, are not concurrent on MRI… at least for mysql.  For folks not using Rails, which already has a mutex lock higher in the stack, this must be a performance issue.  For example,  Merb + DataMapper + MySQL.  If there is a 2s SQL query, all threads in that process stop for 2s.  &lt;/p&gt;
&lt;p&gt;Can others verify?   “select sleep(2) from dual;” is a great way to test for this.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;UPDATE:&lt;/b&gt; Multiple have asked, so to clarify.  The sample code  &lt;a href=&quot;http://pastie.org/248044&quot;&gt;here&lt;/a&gt; creates a new connection PER thread.  The mysql &lt;a href=&quot;http://dev.mysql.com/doc/refman/5.0/en/threaded-clients.html&quot;&gt;docs&lt;/a&gt; states: “Two threads can’t send a query to the MySQL server at the same time on the same connection”, but the test is creating a new connection object per thread, so that should not apply.  &lt;/p&gt;
&lt;p&gt;&lt;b&gt;UPDATE 2:&lt;/b&gt; A couple folks have mentioned asynch drivers.  One for &lt;a href=&quot;http://github.com/oldmoe/mysqlplus%20&quot;&gt;mysql&lt;/a&gt; and one for postgres, but I believe they’re based on &lt;a href=&quot;http://www.espace.com.eg/neverblock/&quot;&gt;NeverBlock&lt;/a&gt;, which is Ruby 1.9 only.  That sounds like awesome progress. What’s the realistic ETA for folks running 1.9 in a production environment?  At least until Christmas for a 1.9 official release?  &lt;/p&gt;
&lt;p&gt;&lt;b&gt;UPDATE 3:&lt;/b&gt; Looks like lots is happening here.  There now is a mysql driver that supports async/threaded operations on 1.8!  See the &lt;a href=&quot;http://www.espace.com.eg/neverblock/blog/2008/08/28/neverblock-mysql-support/&quot;&gt;NeverBlock MySQL&lt;/a&gt; project.  Looking forward to testing this in a production environment.&lt;/p&gt;

&lt;/div&gt;
</content>
 </entry>
 
 <entry>
   <title>Using helpers in a controller: with_helpers</title>
   <link href="http://tech.livingsocial.com/Ops/2008/08/07/using-helpers-in-a-controller-with_helpers.html"/>
   <updated>2008-08-07T00:00:00+00:00</updated>
   <id>http://tech.livingsocial.com/Ops/2008/08/07/using-helpers-in-a-controller-with_helpers</id>
   <content type="html">      &lt;div class=&quot;text&quot;&gt;
          &lt;p&gt;Although there is supposed to be a clear separation between views and controllers, often when it comes to helper functions, there is a small bit of overlap and there are situations where it’d be nice to simply use a few helpers from inside an action.&lt;/p&gt;

&lt;pre class=&quot;code&quot;&gt;&lt;span style=&quot;color:#036; font-weight:bold&quot;&gt;ActionController&lt;/span&gt;::&lt;span style=&quot;color:#036; font-weight:bold&quot;&gt;Base&lt;/span&gt;.class_eval &lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;do&lt;/span&gt;
  &lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;def&lt;/span&gt; &lt;span style=&quot;color:#06B; font-weight:bold&quot;&gt;with_helpers&lt;/span&gt;(&amp;amp;block)
    template = &lt;span style=&quot;color:#036; font-weight:bold&quot;&gt;ActionView&lt;/span&gt;::&lt;span style=&quot;color:#036; font-weight:bold&quot;&gt;Base&lt;/span&gt;.new([],{},&lt;span style=&quot;color:#038; font-weight:bold&quot;&gt;self&lt;/span&gt;)
    template.extend &lt;span style=&quot;color:#038; font-weight:bold&quot;&gt;self&lt;/span&gt;.class.master_helper_module
    add_variables_to_assigns
    template.assigns = &lt;span style=&quot;color:#33B&quot;&gt;@assigns&lt;/span&gt;
    template.send(&lt;span style=&quot;color:#A60&quot;&gt;:assign_variables_from_controller&lt;/span&gt;)
    forget_variables_added_to_assigns
    template.instance_eval(&amp;amp;block)
  &lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;end&lt;/span&gt;
&lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;end&lt;/span&gt;&lt;/pre&gt;
&lt;p&gt;Here is what it looks like in a controller.  Although this is a non-sensical example, it shows off how you can use a helper (i.e. link_to) in an action. It also shows how the instance variables (i.e. @person) set in the action are available in the with_helpers block… the same way that instance variables are available in views.&lt;/p&gt;
&lt;pre class=&quot;code&quot;&gt;&lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;class&lt;/span&gt; &lt;span style=&quot;color:#B06; font-weight:bold&quot;&gt;MyController&lt;/span&gt; &amp;lt; &lt;span style=&quot;color:#036; font-weight:bold&quot;&gt;ApplicationController&lt;/span&gt;
  &lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;def&lt;/span&gt; &lt;span style=&quot;color:#06B; font-weight:bold&quot;&gt;my_action&lt;/span&gt;
    &lt;span style=&quot;color:#33B&quot;&gt;@person&lt;/span&gt; = &lt;span style=&quot;color:#036; font-weight:bold&quot;&gt;Person&lt;/span&gt;.find(params[&lt;span style=&quot;color:#A60&quot;&gt;:id&lt;/span&gt;])
    render &lt;span style=&quot;color:#A60&quot;&gt;:text&lt;/span&gt; =&amp;gt; with_helpers { link_to(&lt;span style=&quot;color:#33B&quot;&gt;@person&lt;/span&gt;.full_name, person_path(&lt;span style=&quot;color:#33B&quot;&gt;@person&lt;/span&gt;)) }
  &lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;end&lt;/span&gt;
&lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;end&lt;/span&gt;&lt;/pre&gt;

&lt;/div&gt;
</content>
 </entry>
 
 <entry>
   <title>Breaking the Rails static asset timestamp cache in development mode</title>
   <link href="http://tech.livingsocial.com/Rails/2008/06/21/breaking-the-rails-static-asset-timestamp-cache-in-development-mode.html"/>
   <updated>2008-06-21T00:00:00+00:00</updated>
   <id>http://tech.livingsocial.com/Rails/2008/06/21/breaking-the-rails-static-asset-timestamp-cache-in-development-mode</id>
   <content type="html">      &lt;div class=&quot;text&quot;&gt;
          &lt;p&gt;Rails automatically adds the File.mtime to static assets when using stylesheet_link_tag and javascript_include_tag.  The file’s mtime is cached to prevent excessive file system access… even in development mode.  This is problematic in a Facebook canvas during development mode because often you won’t immediately see the changes you make to your stylesheets and javascripts.&lt;/p&gt;
&lt;p&gt;Here is a monkey patch you can throw into a config/initializers/break_asset_cache_in_dev_mode.rb to fix this:&lt;/p&gt;

&lt;pre class=&quot;code&quot;&gt;&lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;if&lt;/span&gt; &lt;span style=&quot;color:#036; font-weight:bold&quot;&gt;RAILS_ENV&lt;/span&gt; == &lt;span style=&quot;background-color:#fff0f0&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;'&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;development&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;'&lt;/span&gt;&lt;/span&gt;
  require &lt;span style=&quot;background-color:#fff0f0&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;'&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;action_controller/dispatcher&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;'&lt;/span&gt;&lt;/span&gt;
  &lt;span style=&quot;color:#036; font-weight:bold&quot;&gt;ActionController&lt;/span&gt;::&lt;span style=&quot;color:#036; font-weight:bold&quot;&gt;Dispatcher&lt;/span&gt;.before_dispatch &lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;do&lt;/span&gt;
    &lt;span style=&quot;color:#036; font-weight:bold&quot;&gt;ActionView&lt;/span&gt;::&lt;span style=&quot;color:#036; font-weight:bold&quot;&gt;Base&lt;/span&gt;.computed_public_paths.clear
  &lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;end&lt;/span&gt;
&lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;end&lt;/span&gt;&lt;/pre&gt;

&lt;/div&gt;
</content>
 </entry>
 
 <entry>
   <title>Rake task for syntax checking a Ruby on Rails project</title>
   <link href="http://tech.livingsocial.com/Rails/2008/06/04/rake-task-for-syntax-checking-a-ruby-on-rails-project.html"/>
   <updated>2008-06-04T00:00:00+00:00</updated>
   <id>http://tech.livingsocial.com/Rails/2008/06/04/rake-task-for-syntax-checking-a-ruby-on-rails-project</id>
   <content type="html">&lt;div class=&quot;text&quot;&gt;
          &lt;p&gt;Here’s a quick rake file that will crawl through your Rails project and syntax check ruby, erb, and yml files.  You should always run this before doing a “cap deploy” and it even doesn’t hurt to run it before a “svn commit”.&lt;/p&gt;
&lt;pre class=&quot;code&quot;&gt;require &lt;span style=&quot;background-color:#fff0f0&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;'&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;erb&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;'&lt;/span&gt;&lt;/span&gt;
require &lt;span style=&quot;background-color:#fff0f0&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;'&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;open3&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;'&lt;/span&gt;&lt;/span&gt;
require &lt;span style=&quot;background-color:#fff0f0&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;'&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;yaml&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;'&lt;/span&gt;&lt;/span&gt;

task &lt;span style=&quot;color:#A60&quot;&gt;:check_syntax&lt;/span&gt; =&amp;gt; [&lt;span style=&quot;color:#A60&quot;&gt;:check_ruby&lt;/span&gt;, &lt;span style=&quot;color:#A60&quot;&gt;:check_erb&lt;/span&gt;, &lt;span style=&quot;color:#A60&quot;&gt;:check_yaml&lt;/span&gt;]

task &lt;span style=&quot;color:#A60&quot;&gt;:check_erb&lt;/span&gt; &lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;do&lt;/span&gt;
  (&lt;span style=&quot;color:#036; font-weight:bold&quot;&gt;Dir&lt;/span&gt;[&lt;span style=&quot;background-color:#fff0f0&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;**/*.erb&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;] + &lt;span style=&quot;color:#036; font-weight:bold&quot;&gt;Dir&lt;/span&gt;[&lt;span style=&quot;background-color:#fff0f0&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;**/*.rhtml&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;]).each &lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;do&lt;/span&gt; |file|
    &lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;next&lt;/span&gt; &lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;if&lt;/span&gt; file.match(&lt;span style=&quot;background-color:#fff0f0&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;vendor/rails&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;)
    &lt;span style=&quot;color:#036; font-weight:bold&quot;&gt;Open3&lt;/span&gt;.popen3(&lt;span style=&quot;background-color:#fff0f0&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;'&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;ruby -c&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;'&lt;/span&gt;&lt;/span&gt;) &lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;do&lt;/span&gt; |stdin, stdout, stderr|
      stdin.puts(&lt;span style=&quot;color:#036; font-weight:bold&quot;&gt;ERB&lt;/span&gt;.new(&lt;span style=&quot;color:#036; font-weight:bold&quot;&gt;File&lt;/span&gt;.read(file), &lt;span style=&quot;color:#038; font-weight:bold&quot;&gt;nil&lt;/span&gt;, &lt;span style=&quot;background-color:#fff0f0&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;'&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;'&lt;/span&gt;&lt;/span&gt;).src)
      stdin.close
      &lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;if&lt;/span&gt; error = ((stderr.readline &lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;rescue&lt;/span&gt; &lt;span style=&quot;color:#038; font-weight:bold&quot;&gt;false&lt;/span&gt;))
        puts file + error[&lt;span style=&quot;color:#00D; font-weight:bold&quot;&gt;1&lt;/span&gt;..&lt;span style=&quot;color:#00D; font-weight:bold&quot;&gt;-1&lt;/span&gt;]
      &lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;end&lt;/span&gt;
      stdout.close &lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;rescue&lt;/span&gt; &lt;span style=&quot;color:#038; font-weight:bold&quot;&gt;false&lt;/span&gt;
      stderr.close &lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;rescue&lt;/span&gt; &lt;span style=&quot;color:#038; font-weight:bold&quot;&gt;false&lt;/span&gt;
    &lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;end&lt;/span&gt;
  &lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;end&lt;/span&gt;
&lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;end&lt;/span&gt;

task &lt;span style=&quot;color:#A60&quot;&gt;:check_ruby&lt;/span&gt; &lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;do&lt;/span&gt;
  &lt;span style=&quot;color:#036; font-weight:bold&quot;&gt;Dir&lt;/span&gt;[&lt;span style=&quot;background-color:#fff0f0&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;'&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;**/*.rb&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;'&lt;/span&gt;&lt;/span&gt;].each &lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;do&lt;/span&gt; |file|
    &lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;next&lt;/span&gt; &lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;if&lt;/span&gt; file.match(&lt;span style=&quot;background-color:#fff0f0&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;vendor/rails&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;)
    &lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;next&lt;/span&gt; &lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;if&lt;/span&gt; file.match(&lt;span style=&quot;background-color:#fff0f0&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;vendor/plugins/.*/generators/.*/templates&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;)
    &lt;span style=&quot;color:#036; font-weight:bold&quot;&gt;Open3&lt;/span&gt;.popen3(&lt;span style=&quot;background-color:#fff0f0&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;ruby -c &lt;/span&gt;&lt;span style=&quot;background-color:#fff0f0&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;#{&lt;/span&gt;file&lt;span style=&quot;color:#710&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;) &lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;do&lt;/span&gt; |stdin, stdout, stderr|
      &lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;if&lt;/span&gt; error = ((stderr.readline &lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;rescue&lt;/span&gt; &lt;span style=&quot;color:#038; font-weight:bold&quot;&gt;false&lt;/span&gt;))
        puts error
      &lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;end&lt;/span&gt;
      stdin.close &lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;rescue&lt;/span&gt; &lt;span style=&quot;color:#038; font-weight:bold&quot;&gt;false&lt;/span&gt;
      stdout.close &lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;rescue&lt;/span&gt; &lt;span style=&quot;color:#038; font-weight:bold&quot;&gt;false&lt;/span&gt;
      stderr.close &lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;rescue&lt;/span&gt; &lt;span style=&quot;color:#038; font-weight:bold&quot;&gt;false&lt;/span&gt;
    &lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;end&lt;/span&gt;
  &lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;end&lt;/span&gt;
&lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;end&lt;/span&gt;

task &lt;span style=&quot;color:#A60&quot;&gt;:check_yaml&lt;/span&gt; &lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;do&lt;/span&gt;
  &lt;span style=&quot;color:#036; font-weight:bold&quot;&gt;Dir&lt;/span&gt;[&lt;span style=&quot;background-color:#fff0f0&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;'&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;**/*.yml&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;'&lt;/span&gt;&lt;/span&gt;].each &lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;do&lt;/span&gt; |file|
    &lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;next&lt;/span&gt; &lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;if&lt;/span&gt; file.match(&lt;span style=&quot;background-color:#fff0f0&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;vendor/rails&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;)
    &lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;begin&lt;/span&gt;
      &lt;span style=&quot;color:#036; font-weight:bold&quot;&gt;YAML&lt;/span&gt;.load_file(file)
    &lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;rescue&lt;/span&gt; =&amp;gt; e
      puts &lt;span style=&quot;background-color:#fff0f0&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;background-color:#fff0f0&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;#{&lt;/span&gt;file&lt;span style=&quot;color:#710&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;background-color:#fff0f0&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;#{&lt;/span&gt;(e.message.match(&lt;span style=&quot;background-color:#fff0ff&quot;&gt;&lt;span style=&quot;color:#404&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#808&quot;&gt;on line (&lt;/span&gt;&lt;span style=&quot;color:#04D&quot;&gt;\d&lt;/span&gt;&lt;span style=&quot;color:#808&quot;&gt;+)&lt;/span&gt;&lt;span style=&quot;color:#404&quot;&gt;/&lt;/span&gt;&lt;/span&gt;)[&lt;span style=&quot;color:#00D; font-weight:bold&quot;&gt;1&lt;/span&gt;] + &lt;span style=&quot;background-color:#ffe0e0&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;'&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;'&lt;/span&gt;&lt;/span&gt;) &lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;rescue&lt;/span&gt; &lt;span style=&quot;color:#038; font-weight:bold&quot;&gt;nil&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt; &lt;/span&gt;&lt;span style=&quot;background-color:#fff0f0&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;#{&lt;/span&gt;e.message&lt;span style=&quot;color:#710&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
    &lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;end&lt;/span&gt;
  &lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;end&lt;/span&gt;
&lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;end&lt;/span&gt;&lt;/pre&gt;


&lt;p&gt;And here’s what the output looks like:&lt;/p&gt;

&lt;pre class=&quot;code&quot;&gt;warren:tmp_project$ rake check_syntax
(in /Users/warren/tmp_project)
app/controllers/application.rb:37: syntax error, unexpected '='
app/views/people/home.html.erb:60: syntax error, unexpected '&amp;lt;', expecting $end
vendor/plugins/will_paginate/test/fixtures/users.yml:13: syntax error on line 13, col 0: `dev_&amp;lt;%= digit %&amp;gt;:'&lt;/pre&gt;


&lt;p&gt;This could probably be expanded to support lots of other types of files as well (css, javascripts, etc).&lt;/p&gt;
&lt;h2&gt;Updates:&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Exclude all files in vendor/rails (thanks szeryf)&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
</content>
 </entry>
 
 <entry>
   <title>ESI & Mongrel-ESI.. Request for Feedback</title>
   <link href="http://tech.livingsocial.com/Facebook/2008/06/04/esi-mongrel-esi-request-for-feedback.html"/>
   <updated>2008-06-04T00:00:00+00:00</updated>
   <id>http://tech.livingsocial.com/Facebook/2008/06/04/esi-mongrel-esi-request-for-feedback</id>
   <content type="html">&lt;div class=&quot;text&quot;&gt;

&lt;div class=&quot;thumbnail&quot;&gt;
    &lt;a href=&quot;http://blog.hungrymachine.com/assets/2008/5/31/RailsConf08_Assembling-Pages-Last.pdf.zip&quot;&gt;&lt;img width=&quot;281&quot; height=&quot;177&quot; src=&quot;http://blog.hungrymachine.com/assets/2008/5/31/Picture_14.png&quot;&gt;&lt;/a&gt;
&lt;/div&gt;

&lt;br&gt;&lt;br&gt;&lt;p&gt;The Railsconf08 talk on ESI &amp;amp; Rails has sparked some interest in the community, and Todd, the core &lt;a href=&quot;http://code.google.com/p/mongrel-esi/&quot;&gt;mongrel-esi&lt;/a&gt; maintainer, is asking for feedback on the &lt;a href=&quot;http://groups.google.com/group/mongrel-esi&quot;&gt;mongrel-esi mailing list&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt; The latest rumor is he is working on a &lt;a href=&quot;http://nginx.net/&quot;&gt;nginx&lt;/a&gt; port of mongrel-esi, which I have to admit sounds very interesting…&lt;/p&gt;
&lt;p&gt; How are people planning to use ESI? Can anyone provide Todd with some feedback?&lt;/p&gt;


&lt;pre class=&quot;quote&quot;&gt;
  I'm wondering what is the main set of features preventing folks
today from using mongrel-esi in production?  Is it :

* performance
* documentation
* stability

If it's performance, can someone do some load testing maybe provide
some numbers and even some target numbers?  I am working on an
improved concurrency model, that should help improve page performance
for pages with lots of esi:include tags

if it's documentation, what's the missing bits, and can any of you
help out by filling in the gaps?

if it's stability, can you provide some samples that fail?

-Todd
&lt;/pre&gt;
&lt;/div&gt;</content>
 </entry>
 
 <entry>
   <title>Cleaning up old releases</title>
   <link href="http://tech.livingsocial.com/Ops/2008/06/04/cleaning-up-old-releases.html"/>
   <updated>2008-06-04T00:00:00+00:00</updated>
   <id>http://tech.livingsocial.com/Ops/2008/06/04/cleaning-up-old-releases</id>
   <content type="html">&lt;div class=&quot;text&quot;&gt;
&lt;p&gt;Instead of relaying on running cleanup of old releases via capistrano, we have a cron job to only keep releases for last two days (but at least three latest).&lt;/p&gt;

&lt;pre class=&quot;code&quot;&gt;&lt;span style=&quot;color:#888&quot;&gt;#!/usr/bin/env ruby&lt;/span&gt;

require &lt;span style=&quot;background-color:#fff0f0&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;'&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;fileutils&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;'&lt;/span&gt;&lt;/span&gt;

&lt;span style=&quot;color:#036; font-weight:bold&quot;&gt;KEEP_RELEASES&lt;/span&gt; = &lt;span style=&quot;color:#00D; font-weight:bold&quot;&gt;3&lt;/span&gt;
&lt;span style=&quot;color:#036; font-weight:bold&quot;&gt;KEEP_DAYS&lt;/span&gt; = &lt;span style=&quot;color:#00D; font-weight:bold&quot;&gt;2&lt;/span&gt;
&lt;span style=&quot;color:#036; font-weight:bold&quot;&gt;EXCLUDE_APPS&lt;/span&gt; = &lt;span style=&quot;background-color:#fff0f0&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;%W(&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;uploadr&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;)&lt;/span&gt;&lt;/span&gt;

cut_time = (&lt;span style=&quot;color:#036; font-weight:bold&quot;&gt;Time&lt;/span&gt;.now.utc - &lt;span style=&quot;color:#036; font-weight:bold&quot;&gt;KEEP_DAYS&lt;/span&gt;*&lt;span style=&quot;color:#00D; font-weight:bold&quot;&gt;24&lt;/span&gt;*&lt;span style=&quot;color:#00D; font-weight:bold&quot;&gt;60&lt;/span&gt;*&lt;span style=&quot;color:#00D; font-weight:bold&quot;&gt;60&lt;/span&gt;).strftime(&lt;span style=&quot;background-color:#fff0f0&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;%Y%m%d%H%M%S&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;).to_i

&lt;span style=&quot;color:#036; font-weight:bold&quot;&gt;Dir&lt;/span&gt;[&lt;span style=&quot;background-color:#fff0f0&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;'&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;/u/apps/*&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;'&lt;/span&gt;&lt;/span&gt;].each &lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;do&lt;/span&gt; |app|
  &lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;next&lt;/span&gt; &lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;if&lt;/span&gt; &lt;span style=&quot;color:#036; font-weight:bold&quot;&gt;EXCLUDE_APPS&lt;/span&gt;.include?(&lt;span style=&quot;color:#036; font-weight:bold&quot;&gt;File&lt;/span&gt;.basename(app))
  dirs = &lt;span style=&quot;color:#036; font-weight:bold&quot;&gt;Dir&lt;/span&gt;[&lt;span style=&quot;background-color:#fff0f0&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;background-color:#fff0f0&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;#{&lt;/span&gt; app &lt;span style=&quot;color:#710&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;/releases/*&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;]
  fresh = dirs.select { |dir| (dir.split(&lt;span style=&quot;background-color:#fff0f0&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;'&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;'&lt;/span&gt;&lt;/span&gt;).last).to_i &amp;gt; cut_time }
  latest = dirs.sort.last(&lt;span style=&quot;color:#036; font-weight:bold&quot;&gt;KEEP_RELEASES&lt;/span&gt; )

  (dirs - fresh - latest).each &lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;do&lt;/span&gt; |dir|
    &lt;span style=&quot;color:#036; font-weight:bold&quot;&gt;FileUtils&lt;/span&gt;.rm_rf dir
  &lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;end&lt;/span&gt;
&lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;end&lt;/span&gt;&lt;/pre&gt;
&lt;/div&gt;</content>
 </entry>
 
 <entry>
   <title>RailsConf 2008 Presentation – Assembling Pages Last</title>
   <link href="http://tech.livingsocial.com/Rails/2008/05/31/railsconf-2008-presentation-assembling-pages-last.html"/>
   <updated>2008-05-31T00:00:00+00:00</updated>
   <id>http://tech.livingsocial.com/Rails/2008/05/31/railsconf-2008-presentation-assembling-pages-last</id>
   <content type="html">&lt;div class=&quot;text&quot;&gt;
          &lt;style&gt;
 .thumbnail {  padding:12px; float:left}
&lt;/style&gt;
&lt;div class=&quot;thumbnail&quot;&gt;
    &lt;a href=&quot;http://blog.hungrymachine.com/assets/2008/5/31/RailsConf08_Assembling-Pages-Last.pdf.zip&quot;&gt;&lt;img width=&quot;281&quot; height=&quot;177&quot; src=&quot;http://blog.hungrymachine.com/assets/2008/5/31/Picture_14.png&quot;&gt;&lt;/a&gt;
&lt;/div&gt;
  &lt;br&gt;&lt;br&gt;&lt;p&gt;I presented this morning at RailsConf about Edge Caching and ESI. You can download my presentation below.
&lt;/p&gt;
&lt;p style=&quot;text-align:center;font-size:+1&quot;&gt;
  &lt;a href=&quot;http://blog.hungrymachine.com/assets/2008/5/31/RailsConf08_Assembling-Pages-Last.pdf.zip&quot;&gt;&lt;br&gt;
   Assembling Pages Last: Edge Caching, ESI, and Rails&lt;br&gt;&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;People asked some awesome questions, caught the edge cases I didnt want to cover which were complicated, like authorization/security, multi-level ESI includes, per page include limits, etc. The people at RailsConf are awesome. Thats totally why I enjoy these events.
&lt;/p&gt;
&lt;/div&gt;</content>
 </entry>
 
 <entry>
   <title>The End of Slideshows: Animoto</title>
   <link href="http://tech.livingsocial.com/Uncategorized/2008/05/13/the-end-of-slideshows-animoto.html"/>
   <updated>2008-05-13T00:00:00+00:00</updated>
   <id>http://tech.livingsocial.com/Uncategorized/2008/05/13/the-end-of-slideshows-animoto</id>
   <content type="html">&lt;div class=&quot;text&quot;&gt;
&lt;p&gt;UPDATE:  Animoto just raised a &lt;a href=&quot;http://www.techcrunch.com/2008/05/15/amazon-funds-animoto-music-video-creator/&quot;&gt;round of  investment&lt;/a&gt; from Amazon! Congrats Guys! &lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://www.animoto.com&quot;&gt;Animoto&lt;/a&gt; is a great idea.  They take your photos and create a production quality video to the music of your choice.  Its the end of those boring slide shows, for good.  &lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;div style=&quot;text-align: center;&quot;&gt;
&lt;object id=&quot;W47d804cf2a603f89&quot; width=&quot;432&quot; height=&quot;250&quot; quality=&quot;high&quot; data=&quot;http://widgets.clearspring.com/o/46928cc51133af17/47d804cf2a603f89&quot; pluginspage=&quot;http://www.macromedia.com/go/getflashplayer&quot; type=&quot;application/x-shockwave-flash&quot; wmode=&quot;opaque&quot;&gt;&lt;param name=&quot;wmode&quot; value=&quot;opaque&quot;&gt;
&lt;param name=&quot;movie&quot; value=&quot;http://widgets.clearspring.com/o/46928cc51133af17/47d804cf2a603f89&quot;&gt;
&lt;param name=&quot;scaleMode&quot; value=&quot;showAll&quot;&gt;
&lt;param name=&quot;allowNetworking&quot; value=&quot;all&quot;&gt;
&lt;param name=&quot;allowScriptAccess&quot; value=&quot;always&quot;&gt;
&lt;param name=&quot;flashvars&quot; value=&quot;&quot;&gt;&lt;/object&gt;&lt;br&gt;&lt;br&gt;&lt;span style=&quot;font-size:10px&quot;&gt;(From a recent Techcrunch article &lt;a href=&quot;http://www.techcrunch.com/2008/03/12/animoto-rocks-automatically-turns-your-photos-into-a-music-video-slide-show/&quot;&gt;here&lt;/a&gt;)&lt;/span&gt;
&lt;/div&gt;

&lt;p&gt;We had the pleasure to work with the Animoto guys to launch their Facebook application, &lt;a href=&quot;http://apps.facebook.com/animoto&quot;&gt;“Animoto Videos”&lt;/a&gt;, which leveraged all of the existing photos on Facebook. The growth was amazing.&lt;/p&gt;
&lt;div style=&quot;text-align:center&quot;&gt;
&lt;img src=&quot;http://www.allfacebook.com/images/animoto-screenshot.gif&quot;&gt;&lt;br&gt;&lt;br&gt;&lt;span style=&quot;font-size:10px&quot;&gt;(From a recent AllFacebook article &lt;a href=&quot;http://www.allfacebook.com/2008/03/animoto-challenges-slide-on-facebook/&quot;&gt;here&lt;/a&gt;)&lt;/span&gt;
&lt;/div&gt;
&lt;p&gt;Scaling an application from a few hundred users to over a million in just a few days isnt easy, but we had a great team.  Their backend rendering farm lived in Amazon’s Cloud, and the growth was so impressive, Jeff Bezos even spoke about them at Y Combinator’s &lt;a href=&quot;http://www.startupschool.org/&quot;&gt;Startup School&lt;/a&gt; just a few weeks ago.  From 50 EC2 instances to over 4k in only a few days. See the video below.  &lt;/p&gt;
&lt;div style=&quot;text-align: center;&quot;&gt;
&lt;object width=&quot;520&quot; height=&quot;276&quot;&gt;&lt;param name=&quot;movie&quot; value=&quot;http://www.omnisio.com/bin/Embed.swf?embedID=b6gTwEirOr3zt0adbiFy2w&amp;amp;autoPlay=0&quot;&gt;
&lt;param name=&quot;bgcolor&quot; value=&quot;#FFFFFF&quot;&gt;
&lt;param name=&quot;quality&quot; value=&quot;high&quot;&gt;
&lt;param name=&quot;allowscriptaccess&quot; value=&quot;always&quot;&gt;
&lt;param name=&quot;allowfullscreen&quot; value=&quot;true&quot;&gt;
&lt;embed type=&quot;application/x-shockwave-flash&quot; name=&quot;omnisio_video_b6gTwEirOr3zt0adbiFy2w&quot; src=&quot;http://www.omnisio.com/bin/Embed.swf?embedID=b6gTwEirOr3zt0adbiFy2w&amp;amp;autoPlay=0&quot; bgcolor=&quot;#FFFFFF&quot; quality=&quot;high&quot; allowfullscreen=&quot;true&quot; allowscriptaccess=&quot;always&quot; width=&quot;520&quot; height=&quot;276&quot;&gt;&lt;noembed&gt;&lt;div&gt;
&lt;a href=&quot;http://www.omnisio.com&quot;&gt;Share and annotate your videos&lt;/a&gt; with Omnisio!&lt;/div&gt;
&lt;p&gt;&lt;/p&gt;&lt;/noembed&gt;&lt;/embed&gt;&lt;/object&gt;
&lt;/div&gt;
&lt;p&gt; It was a pleasure working with the entire team from Animoto, RightScale, and Amazon.  See their blog posts about the application &lt;a href=&quot;http://blog.animoto.com/2008/04/21/amazon-ceo-jeff-bezos-on-animoto/&quot;&gt;here&lt;/a&gt;,  &lt;a href=&quot;http://blog.rightscale.com/2008/04/23/animoto-facebook-scale-up/&quot;&gt;here&lt;/a&gt;, and &lt;a href=&quot;http://aws.typepad.com/aws/2008/04/animoto---scali.html&quot;&gt;here&lt;/a&gt;.  &lt;/p&gt;
&lt;p&gt;I’m sure I’ll cross paths with many of you at RailsConf.  First round of beers is on me.&lt;/p&gt;
&lt;/div&gt;
</content>
 </entry>
 
 <entry>
   <title>Advanced Rails Recipes</title>
   <link href="http://tech.livingsocial.com/Rails/2008/05/13/advanced-rails-recipes.html"/>
   <updated>2008-05-13T00:00:00+00:00</updated>
   <id>http://tech.livingsocial.com/Rails/2008/05/13/advanced-rails-recipes</id>
   <content type="html">   &lt;div class=&quot;text&quot;&gt;
          &lt;style&gt;
 .thumbnail {  background:transparent url(http://www.pragprog.com/images/books/190x228/book-shadow.png) no-repeat scroll left top;
                     padding:7px; float:left}
&lt;/style&gt;
&lt;div class=&quot;thumbnail&quot;&gt;
    &lt;a href=&quot;http://pragprog.com/titles/fr_arr/advanced-rails-recipes&quot;&gt;&lt;img width=&quot;190&quot; height=&quot;228&quot; title=&quot;&quot; src=&quot;http://www.pragprog.com/images/covers/190x228/fr_arr.jpg?1194372920&quot; alt=&quot;Advanced Rails Recipes: 84 New Ways to Build Stunning Rails Apps&quot;&gt;&lt;/a&gt;
  &lt;/div&gt;

&lt;p&gt;Congratulations to Mike Clark and the Pragmatic Programmers team for shipping &lt;a href=&quot;http://pragprog.com/titles/fr_arr/advanced-rails-recipes&quot;&gt;Advanced Rails Recipes&lt;/a&gt;.  I highly recommend this book of 70+ recipes on topics ranging from deployment to UI to security and performance, just to list a few.
&lt;/p&gt;
&lt;p&gt;Val, Warren and I are honored to have our recipes included.&lt;/p&gt;
&lt;div style=&quot;padding-left:10px&quot;&gt;
&lt;p&gt;Recipe 34: Play Nice with Facebook&lt;/p&gt;
&lt;p&gt;Recipe 62: Profile in the Browser&lt;/p&gt;
&lt;p&gt;Recipe 67: Encrypt Sensitive Data&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;It was a pleasure to work with Mike Clark on this project.  See his screencast below.
&lt;/p&gt;
&lt;p&gt; &lt;a href=&quot;http://videos.pragprog.com/book-related/fr_arr.mov&quot;&gt;Advanced Rails Recipes Screencast&lt;/a&gt; (33Mb, Quicktime)
&lt;/p&gt;
&lt;/div&gt;
</content>
 </entry>
 
 <entry>
   <title>ActsAsInsertOrUpdate</title>
   <link href="http://tech.livingsocial.com/Performance/2008/04/23/actsasinsertorupdate.html"/>
   <updated>2008-04-23T00:00:00+00:00</updated>
   <id>http://tech.livingsocial.com/Performance/2008/04/23/actsasinsertorupdate</id>
   <content type="html">&lt;div class=&quot;text&quot;&gt;

&lt;h2&gt;Problem&lt;/h2&gt;
&lt;p&gt;
With high volume Rails applications, entities with unique constraints are expensive and error prone to create/update. ActsAsInsertOrUpdate helps solve that problem (if you’re using MySQL), by leveraging the “INSERT … ON DUPLICATE KEY UPDATE” functionality.
&lt;/p&gt;
&lt;h2&gt;Scenario&lt;/h2&gt;
&lt;p&gt; Lets say you have a Person, and Entity, and a Rating. Each user can rate each entity only once, and if they re-rate the entity, it should update the value.&lt;/p&gt;

&lt;pre class=&quot;code&quot;&gt;&lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;class&lt;/span&gt; &lt;span style=&quot;color:#B06; font-weight:bold&quot;&gt;Entity&lt;/span&gt; &amp;lt; &lt;span style=&quot;color:#036; font-weight:bold&quot;&gt;ActiveRecord&lt;/span&gt;::&lt;span style=&quot;color:#036; font-weight:bold&quot;&gt;Base&lt;/span&gt;
  has_many &lt;span style=&quot;color:#A60&quot;&gt;:ratings&lt;/span&gt;
&lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;end&lt;/span&gt;

&lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;class&lt;/span&gt; &lt;span style=&quot;color:#B06; font-weight:bold&quot;&gt;Person&lt;/span&gt; &amp;lt; &lt;span style=&quot;color:#036; font-weight:bold&quot;&gt;ActiveRecord&lt;/span&gt;::&lt;span style=&quot;color:#036; font-weight:bold&quot;&gt;Base&lt;/span&gt;
 has_many &lt;span style=&quot;color:#A60&quot;&gt;:ratings&lt;/span&gt;
&lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;end&lt;/span&gt;

&lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;class&lt;/span&gt; &lt;span style=&quot;color:#B06; font-weight:bold&quot;&gt;Rating&lt;/span&gt; &amp;lt; &lt;span style=&quot;color:#036; font-weight:bold&quot;&gt;ActiveRecord&lt;/span&gt;::&lt;span style=&quot;color:#036; font-weight:bold&quot;&gt;Base&lt;/span&gt;
 belongs_to &lt;span style=&quot;color:#A60&quot;&gt; &lt;img src=&quot;http://blog.hungrymachine.com/wp-includes/images/smilies/icon_razz.gif&quot; alt=&quot;:P&quot; class=&quot;wp-smiley&quot;&gt; erson&lt;/span&gt;
 belongs_to &lt;span style=&quot;color:#A60&quot;&gt;:Entity&lt;/span&gt;
&lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;end&lt;/span&gt;  &lt;/pre&gt;


&lt;p&gt;Here is the table that back’s Rating. Notice the Unique Key constraint on (entity_id, person_id).&lt;/p&gt;
&lt;pre class=&quot;code&quot;&gt;CREATE TABLE `ratings` (
  `id` int(11) NOT NULL auto_increment,
  `rating` tinyint(4) default '0',
  `person_id` int(11) default NULL,
  `entity_id` int(11) default NULL,
  `created_at` datetime default NULL,
  `updated_at` datetime default NULL,
  PRIMARY KEY  (`id`),
  UNIQUE KEY `index_ratings_on_entity_id_and_person_id` (`entity_id`,`person_id`),
)&lt;/pre&gt;
&lt;p&gt;Previously, the logic would be something like:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;1) Check if a rating exists for the User + Entity&lt;/li&gt;
&lt;li&gt;2) If so, update&lt;/li&gt;
&lt;li&gt;3) If not, insert&lt;/li&gt;
&lt;li&gt;4) rescue the insert in case there is a unqiue constraint error&lt;/li&gt;
&lt;li&gt;5) retrieve the record (and/or update with the new rating)&lt;/li&gt;
&lt;p&gt;
If the table is MyISAM, Steps 1-5 aren’t transactionally safe.  If you’re using InnoDB, and experience heavy volumes of traffic, you’re prone to Deadlock’s.  This is even more of a concern is the unique entity is shared across multiple users, as seen with a recent client of ours.
&lt;/p&gt;
&lt;h2&gt;Solution:&lt;/h2&gt;
&lt;pre class=&quot;code&quot;&gt;&lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;class&lt;/span&gt; &lt;span style=&quot;color:#B06; font-weight:bold&quot;&gt;Rating&lt;/span&gt; &amp;lt; &lt;span style=&quot;color:#036; font-weight:bold&quot;&gt;ActiveRecord&lt;/span&gt;::&lt;span style=&quot;color:#036; font-weight:bold&quot;&gt;Base&lt;/span&gt;
 belongs_to &lt;span style=&quot;color:#A60&quot;&gt; &lt;img src=&quot;http://blog.hungrymachine.com/wp-includes/images/smilies/icon_razz.gif&quot; alt=&quot;:P&quot; class=&quot;wp-smiley&quot;&gt; erson&lt;/span&gt;
 belongs_to &lt;span style=&quot;color:#A60&quot;&gt;:Entity&lt;/span&gt;
 acts_as_insert_or_update &lt;span style=&quot;color:#A60&quot;&gt;:field_to_update&lt;/span&gt; =&amp;gt; &lt;span style=&quot;background-color:#fff0f0&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;rating&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;end&lt;/span&gt;  &lt;/pre&gt;
&lt;p&gt;Now Steps 1-5 above become, just one.  Rating.create(..)&lt;/p&gt;
&lt;p&gt;In the background, ActsAsInsertOrUpdate overwrites the implementation of ActionRecord:Base#create, to leverage an often unsed feature of MySQL called INSERT … ON DUPLICATE KEY UPDATE. As configured above, if a duplicate record is found for the unique constraint, the rating field will be updated with the new value. &lt;/p&gt;
&lt;h2&gt;Caution&lt;/h2&gt;
&lt;p&gt;This is a brute force hack on ActiveRecord::Base#create.  Use at your own risk.&lt;/p&gt;
&lt;h2&gt;Code&lt;/h2&gt;
&lt;p&gt;Waiting for a rubyforge account.  Will post more info soon.&lt;/p&gt;
        &lt;/ul&gt;
&lt;/div&gt;
</content>
 </entry>
 
 <entry>
   <title>MySQL Stored Function: parsing a JSON encoded string</title>
   <link href="http://tech.livingsocial.com/2008/04/14/mysql-stored-function-parsing-a-json-encoded-string.html"/>
   <updated>2008-04-14T00:00:00+00:00</updated>
   <id>http://tech.livingsocial.com/2008/04/14/mysql-stored-function-parsing-a-json-encoded-string</id>
   <content type="html">&lt;div class=&quot;text&quot;&gt;

&lt;p&gt;For analytics purposes, we ended up storing JSON-encoded data as a column in a mysql table.  Although we don’t often need to query it directly, from time to time, it makes things a bit easier/faster.  Below is a MySQL stored function that takes two parameters (a JSON encoded string, and the name of a key) and returns the value associated with that key.&lt;/p&gt;
&lt;pre class=&quot;code&quot;&gt;
CREATE FUNCTION JSON(`json` TEXT, `search_key` VARCHAR(255)) RETURNS TEXT DETERMINISTIC BEGIN

  DECLARE i INT DEFAULT 1;
  DECLARE json_length INT DEFAULT LENGTH(json);
  DECLARE state ENUM('reading_key','done_reading_key','reading_string', 'reading_array');
  DECLARE tmp_key TEXT;
  DECLARE tmp_value TEXT;
  DECLARE current_char VARCHAR(1);

  WHILE i
&lt;h2&gt;Examples&lt;/h2&gt;
&lt;p&gt;Here's a few examples of how it can be used:&lt;/p&gt;
&lt;pre class=&quot;code&quot;&gt;
SELECT JSON('{&quot;key1&quot;:&quot;val\\&quot;ue1&quot;,&quot;key2&quot;:&quot;value2&quot;,&quot;key3&quot;:[&quot;array1&quot;,&quot;array2&quot;],&quot;key4&quot;:&quot;value4&quot;}', 'key1');
# returns 'val&quot;ue1'

SELECT JSON('{&quot;key1&quot;:&quot;val\\&quot;ue1&quot;,&quot;key2&quot;:&quot;value2&quot;,&quot;key3&quot;:[&quot;array1&quot;,&quot;array2&quot;],&quot;key4&quot;:&quot;value4&quot;}', 'key2');
# returns 'value2'

SELECT JSON('{&quot;key1&quot;:&quot;val\\&quot;ue1&quot;,&quot;key2&quot;:&quot;value2&quot;,&quot;key3&quot;:[&quot;array1&quot;,&quot;array2&quot;],&quot;key4&quot;:&quot;value4&quot;}', 'key3');
# returns '&quot;array1&quot;,&quot;array2&quot;'

SELECT JSON('{&quot;key1&quot;:&quot;val\\&quot;ue1&quot;,&quot;key2&quot;:&quot;value2&quot;,&quot;key3&quot;:[&quot;array1&quot;,&quot;array2&quot;],&quot;key4&quot;:&quot;value4&quot;}', 'key4');
# returns 'value4'

SELECT JSON('{&quot;key1&quot;:&quot;val\\&quot;ue1&quot;,&quot;key2&quot;:&quot;value2&quot;,&quot;key3&quot;:[&quot;array1&quot;,&quot;array2&quot;],&quot;key4&quot;:&quot;value4&quot;}', 'key5');
# returns NULL
&lt;/pre&gt;
&lt;h2&gt;Notes:&lt;/h2&gt;
&lt;p&gt;If you're trying to run this in the MySQL console, you'll need to set the DELIMITER to be something other than a semi-colon.  Before executing the above, run &quot;DELIMITER $$&quot; and after executing it, run &quot;$$&quot; and then &quot;DELIMITER ;&quot; to set your delimiter back to semi-colon.&lt;/p&gt;
&lt;p&gt;If you're trying to run this in a Rails migration, don't forget to escape the back-slashes (i.e. '\\' should become '\\\\')&lt;/p&gt;
&lt;p&gt;Although this handles several simple use cases of extracting JSON-encoded data, it is by no means comprehensive.   There are many JSON-encoded structures that this will not work on.  This will not work correctly with nested arrays, or with named hashes.&lt;/p&gt;
&lt;p&gt;The performance of this is pretty slow.  A better approach would be to create a UDF that plugs into MySQL.  Here's a UDF to encode JSON data, but not decode: &lt;a href=&quot;http://www.mysqludf.org/lib_mysqludf_json/index.php&quot;&gt;http://www.mysqludf.org/lib_mysqludf_json/index.php&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Faster Implementation:&lt;/h2&gt;
&lt;p&gt;Here's a faster version, but it's not quite as robust:&lt;/p&gt;
&lt;pre class=&quot;code&quot;&gt;
CREATE FUNCTION JSON_FAST(`json` TEXT, `search_key` VARCHAR(255)) RETURNS TEXT DETERMINISTIC BEGIN
  IF INSTR(json, CONCAT('&quot;', search_key, '&quot;:&quot;')) THEN
    RETURN SUBSTRING_INDEX(SUBSTRING(json, INSTR(json, CONCAT('&quot;', search_key, '&quot;:&quot;')) +
           LENGTH(search_key) + 4), '&quot;', 1);
  ELSEIF INSTR(json, CONCAT('&quot;', search_key, '&quot;: &quot;')) THEN
    RETURN SUBSTRING_INDEX(SUBSTRING(json, INSTR(json, CONCAT('&quot;', search_key, '&quot;: &quot;')) +
           LENGTH(search_key) + 5), '&quot;', 1);
  ELSE
    RETURN NULL;
  END IF;
END
&lt;/pre&gt;
&lt;p&gt;Here's some key differences:&lt;/p&gt;
&lt;pre class=&quot;code&quot;&gt;
SELECT JSON('{&quot;key&quot;:&quot;value \&quot;plus quotes\&quot;&quot;}', 'key');
# returns 'value &quot;plus quotes&quot;'
SELECT JSON_FAST('{&quot;key&quot;:&quot;value \&quot;plus quotes\&quot;&quot;}', 'key');
# returns 'value \'

SELECT JSON('{&quot;key&quot;:[&quot;value1&quot;,&quot;value2&quot;]}', 'key');
# returns '&quot;value1&quot;,&quot;value2&quot;'
SELECT JSON_FAST('{&quot;key&quot;:[&quot;value1&quot;,&quot;value2&quot;]}', 'key');
# returns NULL
&lt;/pre&gt;

        &lt;/pre&gt;
&lt;/div&gt;

</content>
 </entry>
 
 <entry>
   <title>Curb your Net::HTTP</title>
   <link href="http://tech.livingsocial.com/Ops/2008/04/08/an-alternative-to-net-http.html"/>
   <updated>2008-04-08T00:00:00+00:00</updated>
   <id>http://tech.livingsocial.com/Ops/2008/04/08/an-alternative-to-net-http</id>
   <content type="html">&lt;div class=&quot;text&quot;&gt;
&lt;p&gt;&lt;img style=&quot;float:left;padding:0px 12px 12px 12px&quot; src=&quot;http://farm1.static.flickr.com/127/373875465_3134e00927_m.jpg&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://curb.rubyforge.org/&quot;&gt;Curb&lt;/a&gt; is a ruby binding for &lt;a href=&quot;http://curl.haxx.se/&quot;&gt;libcurl&lt;/a&gt;. We’ve had sporadic issues with Net::HTTP, which this might aleviate via native dns, native timeouts, performance improvements, etc.   It wouldnt be hard to re-implement ActiveResource, rfacebook, myspace-ruby, etc to use it instead. Anyone using this already? &lt;/p&gt;
&lt;pre class=&quot;code&quot;&gt;
sudo gem install curb
&lt;/pre&gt;
&lt;pre class=&quot;code&quot;&gt;require &lt;span style=&quot;background-color:#fff0f0&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;'&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;rubygems&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;'&lt;/span&gt;&lt;/span&gt;
require &lt;span style=&quot;background-color:#fff0f0&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;'&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;curb&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;'&lt;/span&gt;&lt;/span&gt;
require &lt;span style=&quot;background-color:#fff0f0&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;net/http&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
require &lt;span style=&quot;background-color:#fff0f0&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;'&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;benchmark&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;'&lt;/span&gt;&lt;/span&gt;

iterations = &lt;span style=&quot;color:#00D; font-weight:bold&quot;&gt;40&lt;/span&gt;
&lt;span style=&quot;color:#036; font-weight:bold&quot;&gt;Benchmark&lt;/span&gt;.bm &lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;do&lt;/span&gt; |x|
  x.report(&lt;span style=&quot;background-color:#fff0f0&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;curb&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;) &lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;do&lt;/span&gt;
    iterations.times &lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;do&lt;/span&gt;
      c = &lt;span style=&quot;color:#036; font-weight:bold&quot;&gt;Curl&lt;/span&gt;::&lt;span style=&quot;color:#036; font-weight:bold&quot;&gt;Easy&lt;/span&gt;.perform(&lt;span style=&quot;background-color:#fff0f0&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;http://www.google.com&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;)
      &lt;span style=&quot;color:#888&quot;&gt;#puts c.body_str&lt;/span&gt;
    &lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;end&lt;/span&gt;
  &lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;end&lt;/span&gt;
  x.report(&lt;span style=&quot;background-color:#fff0f0&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;net/http&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;)  &lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;do&lt;/span&gt;
    iterations.times &lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;do&lt;/span&gt;
      http = &lt;span style=&quot;color:#036; font-weight:bold&quot;&gt;Net&lt;/span&gt;::&lt;span style=&quot;color:#036; font-weight:bold&quot;&gt;HTTP&lt;/span&gt;.start(&lt;span style=&quot;background-color:#fff0f0&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;www.google.com&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;)
      req = &lt;span style=&quot;color:#036; font-weight:bold&quot;&gt;Net&lt;/span&gt;::&lt;span style=&quot;color:#036; font-weight:bold&quot;&gt;HTTP&lt;/span&gt;::&lt;span style=&quot;color:#036; font-weight:bold&quot;&gt;Get&lt;/span&gt;.new(&lt;span style=&quot;background-color:#fff0f0&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;)
      res = http.request(req)
      &lt;span style=&quot;color:#888&quot;&gt;#puts res.body&lt;/span&gt;
    &lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;end&lt;/span&gt;
  &lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;end&lt;/span&gt;
&lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;end&lt;/span&gt;&lt;/pre&gt;
&lt;pre class=&quot;code&quot;&gt;
             user     system      total        real
curb      0.010000   0.030000   0.040000 (  4.019197)
net/http  0.140000   0.110000   0.250000 (  4.155106)
&lt;/pre&gt;
&lt;/div&gt;
</content>
 </entry>
 
 <entry>
   <title>Agressive Timeouts On External API Calls</title>
   <link href="http://tech.livingsocial.com/Ops/2008/03/31/agressive-timeouts-on-external-api-calls.html"/>
   <updated>2008-03-31T00:00:00+00:00</updated>
   <id>http://tech.livingsocial.com/Ops/2008/03/31/agressive-timeouts-on-external-api-calls</id>
   <content type="html">&lt;div class=&quot;text&quot;&gt;
&lt;p&gt;One of the challenges with writing a Facebook or Bebo application is staying within a limit it gives you to respond with data before it shows the &lt;em&gt;Application Did Not Respond&lt;/em&gt; page to a user. Having a content reach application calling external APIs, like Amazon or YouTube, with response times beyond your control, forces you to keep such calls short to allow extra time for processing. We usually wrap them in aggressive timeouts with a retry. As an example is this code from the &lt;a href=&quot;http://www.pluitsolutions.com/projects/amazon-ecs&quot;&gt;Ruby Amazon E-Commerce &lt;span class=&quot;caps&quot;&gt;REST&lt;/span&gt; Service &lt;span class=&quot;caps&quot;&gt;API&lt;/span&gt;&lt;/a&gt; gem rewritten to limit a single call attempt to two seconds with one more retry.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Original Code&lt;/strong&gt;&lt;/p&gt;

&lt;pre class=&quot;code&quot;&gt;&lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;module&lt;/span&gt; &lt;span style=&quot;color:#B06; font-weight:bold&quot;&gt;Amazon&lt;/span&gt;
  &lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;class&lt;/span&gt; &lt;span style=&quot;color:#B06; font-weight:bold&quot;&gt;Ecs&lt;/span&gt;

    &lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;def&lt;/span&gt; &lt;span style=&quot;color:#038; font-weight:bold&quot;&gt;self&lt;/span&gt;.send_request(opts)
      request_url = prepare_url(opts)

      res = &lt;span style=&quot;color:#036; font-weight:bold&quot;&gt;Net&lt;/span&gt;::&lt;span style=&quot;color:#036; font-weight:bold&quot;&gt;HTTP&lt;/span&gt;.get_response(&lt;span style=&quot;color:#036; font-weight:bold&quot;&gt;URI&lt;/span&gt;::parse(request_url))
      &lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;unless&lt;/span&gt; res.kind_of? &lt;span style=&quot;color:#036; font-weight:bold&quot;&gt;Net&lt;/span&gt;::&lt;span style=&quot;color:#036; font-weight:bold&quot;&gt;HTTPSuccess&lt;/span&gt;
        raise &lt;span style=&quot;color:#036; font-weight:bold&quot;&gt;Amazon&lt;/span&gt;::&lt;span style=&quot;color:#036; font-weight:bold&quot;&gt;RequestError&lt;/span&gt;, &lt;span style=&quot;background-color:#fff0f0&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;HTTP Response: &lt;/span&gt;&lt;span style=&quot;background-color:#fff0f0&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;#{&lt;/span&gt;res.code&lt;span style=&quot;color:#710&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt; &lt;/span&gt;&lt;span style=&quot;background-color:#fff0f0&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;#{&lt;/span&gt;res.message&lt;span style=&quot;color:#710&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
      &lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;end&lt;/span&gt;
      &lt;span style=&quot;color:#036; font-weight:bold&quot;&gt;Response&lt;/span&gt;.new(res.body)
    &lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;end&lt;/span&gt;

  &lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;end&lt;/span&gt;
&lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;end&lt;/span&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;Modified Code&lt;/strong&gt;&lt;/p&gt;

&lt;pre class=&quot;code&quot;&gt;&lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;module&lt;/span&gt; &lt;span style=&quot;color:#B06; font-weight:bold&quot;&gt;Amazon&lt;/span&gt;
  &lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;class&lt;/span&gt; &lt;span style=&quot;color:#B06; font-weight:bold&quot;&gt;Ecs&lt;/span&gt;

    &lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;class&lt;/span&gt; &lt;span style=&quot;color:#B06; font-weight:bold&quot;&gt;EmptyResponse&lt;/span&gt;
      &lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;def&lt;/span&gt; &lt;span style=&quot;color:#06B; font-weight:bold&quot;&gt;items&lt;/span&gt;; []; &lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;end&lt;/span&gt;
      &lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;def&lt;/span&gt; &lt;span style=&quot;color:#06B; font-weight:bold&quot;&gt;total_pages&lt;/span&gt;; &lt;span style=&quot;color:#00D; font-weight:bold&quot;&gt;0&lt;/span&gt;; &lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;end&lt;/span&gt;
    &lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;end&lt;/span&gt;

    &lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;def&lt;/span&gt; &lt;span style=&quot;color:#038; font-weight:bold&quot;&gt;self&lt;/span&gt;.send_request(opts)

      res = timed_try(request_url, &lt;span style=&quot;color:#00D; font-weight:bold&quot;&gt;2&lt;/span&gt;) &lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;do&lt;/span&gt; |url|

        uri = &lt;span style=&quot;color:#036; font-weight:bold&quot;&gt;URI&lt;/span&gt;::parse(url)
        req = &lt;span style=&quot;color:#036; font-weight:bold&quot;&gt;Net&lt;/span&gt;::&lt;span style=&quot;color:#036; font-weight:bold&quot;&gt;HTTP&lt;/span&gt;.new(uri.host, uri.port)

        &lt;span style=&quot;color:#888&quot;&gt;# Agressive timeouts&lt;/span&gt;
        req.open_timeout = &lt;span style=&quot;color:#00D; font-weight:bold&quot;&gt;1&lt;/span&gt;
        req.read_timeout = &lt;span style=&quot;color:#00D; font-weight:bold&quot;&gt;2&lt;/span&gt;

        req.start { |http| http.request_get(url) }

      &lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;end&lt;/span&gt;

      res.kind_of?(&lt;span style=&quot;color:#036; font-weight:bold&quot;&gt;Net&lt;/span&gt;::&lt;span style=&quot;color:#036; font-weight:bold&quot;&gt;HTTPSuccess&lt;/span&gt;) ? &lt;span style=&quot;color:#036; font-weight:bold&quot;&gt;Response&lt;/span&gt;.new(res.body) : &lt;span style=&quot;color:#036; font-weight:bold&quot;&gt;EmptyResponse&lt;/span&gt;.new

    &lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;end&lt;/span&gt;

private

     &lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;def&lt;/span&gt; &lt;span style=&quot;color:#06B; font-weight:bold&quot;&gt;timed_try&lt;/span&gt;(url, attempts, &amp;amp;block)

       attempt = &lt;span style=&quot;color:#00D; font-weight:bold&quot;&gt;1&lt;/span&gt;
       &lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;begin&lt;/span&gt;
         block.call(url)
       &lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;rescue&lt;/span&gt; &lt;span style=&quot;color:#036; font-weight:bold&quot;&gt;Timeout&lt;/span&gt;::&lt;span style=&quot;color:#036; font-weight:bold&quot;&gt;Error&lt;/span&gt;
         &lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;if&lt;/span&gt; attempt &amp;gt;= attempts
           &lt;span style=&quot;color:#036; font-weight:bold&quot;&gt;RAILS_DEFAULT_LOGGER&lt;/span&gt;.warn &lt;span style=&quot;background-color:#fff0f0&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;[amazon_api] gave up after attempt #&lt;/span&gt;&lt;span style=&quot;background-color:#fff0f0&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;#{&lt;/span&gt; attempt &lt;span style=&quot;color:#710&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt; to get data from &lt;/span&gt;&lt;span style=&quot;background-color:#fff0f0&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;#{&lt;/span&gt; url &lt;span style=&quot;color:#710&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
           &lt;span style=&quot;color:#038; font-weight:bold&quot;&gt;nil&lt;/span&gt;
         &lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;else&lt;/span&gt;
           &lt;span style=&quot;color:#036; font-weight:bold&quot;&gt;RAILS_DEFAULT_LOGGER&lt;/span&gt;.warn &lt;span style=&quot;background-color:#fff0f0&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;[amazon_api] attempt #&lt;/span&gt;&lt;span style=&quot;background-color:#fff0f0&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;#{&lt;/span&gt; attempt &lt;span style=&quot;color:#710&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt; timed out on getting data from &lt;/span&gt;&lt;span style=&quot;background-color:#fff0f0&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;#{&lt;/span&gt; url &lt;span style=&quot;color:#710&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
           attempt += &lt;span style=&quot;color:#00D; font-weight:bold&quot;&gt;1&lt;/span&gt;
           &lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;retry&lt;/span&gt;
         &lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;end&lt;/span&gt;
       &lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;end&lt;/span&gt;

     &lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;end&lt;/span&gt;

  &lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;end&lt;/span&gt;
&lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;end&lt;/span&gt;&lt;/pre&gt;

&lt;/div&gt;
</content>
 </entry>
 
 <entry>
   <title>Reviewing Application Health with HAProxy Stats</title>
   <link href="http://tech.livingsocial.com/Ops/2008/03/27/analyzing-application-performance-with-haproxy-stats.html"/>
   <updated>2008-03-27T00:00:00+00:00</updated>
   <id>http://tech.livingsocial.com/Ops/2008/03/27/analyzing-application-performance-with-haproxy-stats</id>
   <content type="html">&lt;div class=&quot;text&quot;&gt;
  &lt;p&gt;One of the methods we use for checking the health of &lt;a href=&quot;http://www.livingsocial.com/&quot;&gt;our applications&lt;/a&gt; is stats collected from &lt;a href=&quot;http://haproxy.1wt.eu/&quot;&gt;HAProxy&lt;/a&gt;. We utilize it to see how many requests are scheduled for execution on mongrel instances. The graph is one indication of how our applications perform. When we launched the new version of the site three weeks ago, the graph for a single vertical (ReadingSocial) on a typical Tuesday looked like this:&lt;/p&gt;

  &lt;img src=&quot;http://blog.hungrymachine.com/assets/2008/3/27/old-hastats.jpg&quot; width=&quot;100%&quot;&gt;

  &lt;p&gt;
  So, between porting all verticals to Myspace, Orkut, Bebo, and enhancing the functionality, we spent some time on optimization. In addition to analyzing slow-query logs with &lt;a href=&quot;http://hackmysql.com/mysqlsla&quot;&gt;mysqlsla&lt;/a&gt;, Aaron wrapped all external API calls (and we do a lot of them – to Amazon, Facebook, Myspace, etc) in slow monitoring so we could see where the latest external bottleneck was so we could fix it one by one. Three weeks later the graph became much more peaceful:&lt;/p&gt;


  &lt;img src=&quot;http://blog.hungrymachine.com/assets/2008/3/27/new-hastats.jpg&quot; width=&quot;100%&quot;&gt;
&lt;/div&gt;</content>
 </entry>
 
 <entry>
   <title>Viva LivingSocial!</title>
   <link href="http://tech.livingsocial.com/Uncategorized/2008/03/15/viva-livingsocial.html"/>
   <updated>2008-03-15T00:00:00+00:00</updated>
   <id>http://tech.livingsocial.com/Uncategorized/2008/03/15/viva-livingsocial</id>
   <content type="html">&lt;div class=&quot;text&quot;&gt;
  &lt;p&gt;You haven’t heard from us for a while because we were working on a new project – &lt;a href=&quot;http://livingsocial.com&quot;&gt;LivingSocial&lt;/a&gt; – the web-site that spreads across all major social networks (Facebook, Myspace, Bebo, Orkut) allowing people to talk to each other about their interests without barriers. We are going to speak more about it &lt;a href=&quot;http://blog.livingsocial.com/&quot;&gt;in a dedicated blog&lt;/a&gt; while keeping this one for posts on Rails and other technologies.&lt;/p&gt;
&lt;/div&gt;
</content>
 </entry>
 
 <entry>
   <title>Simple Google Pie Chart Graph in Rails</title>
   <link href="http://tech.livingsocial.com/Rails/2008/02/16/simple-google-pie-chart-graph-in-rails.html"/>
   <updated>2008-02-16T00:00:00+00:00</updated>
   <id>http://tech.livingsocial.com/Rails/2008/02/16/simple-google-pie-chart-graph-in-rails</id>
   <content type="html">&lt;div class=&quot;text&quot;&gt;
  &lt;p&gt;Although there are many comprehensive libraries out there for google graphs in Rails, all we needed was a quick and simple pie chart.  Here’s what we came up with:&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;/p&gt;
&lt;pre class=&quot;code&quot;&gt;
module ApplicationHelper
  def google_pie_chart(data, options = {})
    options[:width] ||= 250
    options[:height] ||= 100
    options[:colors] = %w(0DB2AC F5DD7E FC8D4D FC694D FABA32 704948 968144 C08FBC ADD97E)
    dt = &quot;ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-.&quot;
    options[:divisor] ||= 1

    while (data.map { |k,v| v }.max / options[:divisor] &amp;gt;= 4096) do
      options[:divisor] *= 10
    end

    opts = {
      :cht =&amp;gt; &quot;p&quot;,
      :chd =&amp;gt; &quot;e:#{data.map{|k,v|v=v/options[:divisor];dt[v/64..v/64]+dt[v%64..v%64]}}&quot;,
      :chl =&amp;gt; &quot;#{data.map { |k,v| CGI::escape(k + &quot; (#{v})&quot;)}.join('|')}&quot;,
      :chs =&amp;gt; &quot;#{options[:width]}x#{options[:height]}&quot;,
      :chco =&amp;gt; options[:colors].slice(0, data.length).join(',')
    }

    image_tag(&quot;http://chart.apis.google.com/chart?#{opts.map{|k,v|&quot;#{k}=#{v}&quot;}.join('&amp;amp;')}&quot;)
  rescue
  end
end
&lt;/pre&gt;
&lt;p&gt;Here’s an example of how to use it:&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;/p&gt;
&lt;pre class=&quot;code&quot;&gt;
&amp;lt;%=google_pie_chart([[&quot;Very Liberal&quot;, 8], [&quot;Liberal&quot;, 22], [&quot;Moderate&quot;, 9], [&quot;Conservative&quot;, 4], [&quot;Very Conservative&quot;, 1]], :width =&amp;gt; 626, :height =&amp;gt; 300) %&amp;gt;
&lt;/pre&gt;
&lt;p&gt;And what it renders:&lt;br&gt;&lt;br&gt;&lt;img src=&quot;http://chart.apis.google.com/chart?chl=Very+Liberal+%288%29%7CLiberal+%2822%29%7CModerate+%289%29%7CConservative+%284%29%7CVery+Conservative+%281%29&amp;amp;chs=626x300&amp;amp;chco=0DB2AC,F5DD7E,FC8D4D,FC694D,FABA32&amp;amp;cht=p&amp;amp;chd=e:AIAWAJAEAB&quot;&gt;&lt;/p&gt;
&lt;/div&gt;
</content>
 </entry>
 
 <entry>
   <title>Leverage Rails Resource Routes on Facebook</title>
   <link href="http://tech.livingsocial.com/Rails/2008/01/07/leverage-rails-resource-routes-on-facebook.html"/>
   <updated>2008-01-07T00:00:00+00:00</updated>
   <id>http://tech.livingsocial.com/Rails/2008/01/07/leverage-rails-resource-routes-on-facebook</id>
   <content type="html">&lt;div class=&quot;text&quot;&gt;
&lt;p&gt;Since all canvas page views are proxied through POSTs, resource routes were hopelessly broken. The Facebook platform team was kind enough to add a new feature just for us rails folks: a new signed parameter that indicates the original request type (i.e. POST v. GET) against canvas pages.&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;
Here’s a small patch you can stick at the end of environment.rb to restore REST-ful routes.&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;/p&gt;
&lt;pre class=&quot;textmate-source&quot;&gt;&lt;span class=&quot;source source_ruby&quot;&gt;&lt;span class=&quot;meta meta_class meta_class_ruby&quot;&gt;&lt;span class=&quot;keyword keyword_control keyword_control_class keyword_control_class_ruby&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;entity entity_name entity_name_type entity_name_type_class entity_name_type_class_ruby&quot;&gt;ActionController::Routing::RouteSet&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;meta meta_function meta_function_method meta_function_method_with-arguments meta_function_method_with-arguments_ruby&quot;&gt;&lt;span class=&quot;keyword keyword_control keyword_control_def keyword_control_def_ruby&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;entity entity_name entity_name_function entity_name_function_ruby&quot;&gt;extract_request_environment&lt;/span&gt;&lt;span class=&quot;punctuation punctuation_definition punctuation_definition_parameters punctuation_definition_parameters_ruby&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;variable variable_parameter variable_parameter_function variable_parameter_function_ruby&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;punctuation punctuation_definition punctuation_definition_parameters punctuation_definition_parameters_ruby&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
    contents &lt;span class=&quot;keyword keyword_operator keyword_operator_assignment keyword_operator_assignment_ruby&quot;&gt;=&lt;/span&gt; request&lt;span class=&quot;punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby&quot;&gt;.&lt;/span&gt;body&lt;span class=&quot;punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby&quot;&gt;.&lt;/span&gt;read
    facebook_method_override &lt;span class=&quot;keyword keyword_operator keyword_operator_assignment keyword_operator_assignment_ruby&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;constant constant_language constant_language_ruby&quot;&gt;nil&lt;/span&gt;
    &lt;span class=&quot;keyword keyword_control keyword_control_ruby&quot;&gt;if&lt;/span&gt; contents &lt;span class=&quot;keyword keyword_operator keyword_operator_comparison keyword_operator_comparison_ruby&quot;&gt;=~&lt;/span&gt; &lt;span class=&quot;string string_regexp string_regexp_classic string_regexp_classic_ruby&quot;&gt;&lt;span class=&quot;punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_ruby&quot;&gt;/&lt;/span&gt;fb_sig_request_method=&lt;span class=&quot;string string_regexp string_regexp_group string_regexp_group_ruby&quot;&gt;&lt;span class=&quot;punctuation punctuation_definition punctuation_definition_group punctuation_definition_group_ruby&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;string string_regexp string_regexp_character-class string_regexp_character-class_ruby&quot;&gt;&lt;span class=&quot;punctuation punctuation_definition punctuation_definition_character-class punctuation_definition_character-class_ruby&quot;&gt;[&lt;/span&gt;A-Z&lt;span class=&quot;punctuation punctuation_definition punctuation_definition_character-class punctuation_definition_character-class_ruby&quot;&gt;]&lt;/span&gt;&lt;/span&gt;+&lt;span class=&quot;punctuation punctuation_definition punctuation_definition_group punctuation_definition_group_ruby&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_ruby&quot;&gt;/&lt;/span&gt;&lt;/span&gt;
      facebook_method_override &lt;span class=&quot;keyword keyword_operator keyword_operator_assignment keyword_operator_assignment_ruby&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;variable variable_other variable_other_readwrite variable_other_readwrite_global variable_other_readwrite_global_pre-defined variable_other_readwrite_global_pre-defined_ruby&quot;&gt;&lt;span class=&quot;punctuation punctuation_definition punctuation_definition_variable punctuation_definition_variable_ruby&quot;&gt;$&lt;/span&gt;1&lt;/span&gt;
    &lt;span class=&quot;keyword keyword_control keyword_control_ruby&quot;&gt;end&lt;/span&gt;
    request&lt;span class=&quot;punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby&quot;&gt;.&lt;/span&gt;body&lt;span class=&quot;punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby&quot;&gt;.&lt;/span&gt;string &lt;span class=&quot;keyword keyword_operator keyword_operator_assignment keyword_operator_assignment_ruby&quot;&gt;=&lt;/span&gt; contents
    &lt;span class=&quot;punctuation punctuation_section punctuation_section_scope punctuation_section_scope_ruby&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;meta meta_syntax meta_syntax_ruby meta_syntax_ruby_start-block&quot;&gt; &lt;/span&gt;&lt;span class=&quot;constant constant_other constant_other_symbol constant_other_symbol_ruby&quot;&gt;&lt;span class=&quot;punctuation punctuation_definition punctuation_definition_constant punctuation_definition_constant_ruby&quot;&gt;:&lt;/span&gt;method&lt;/span&gt; &lt;span class=&quot;punctuation punctuation_separator punctuation_separator_key-value&quot;&gt;=&amp;gt;&lt;/span&gt; facebook_method_override &lt;span class=&quot;keyword keyword_operator keyword_operator_comparison keyword_operator_comparison_ruby&quot;&gt;?&lt;/span&gt; facebook_method_override&lt;span class=&quot;punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby&quot;&gt;.&lt;/span&gt;downcase&lt;span class=&quot;punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby&quot;&gt;.&lt;/span&gt;intern &lt;span class=&quot;punctuation punctuation_separator punctuation_separator_other punctuation_separator_other_ruby&quot;&gt;:&lt;/span&gt; request&lt;span class=&quot;punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby&quot;&gt;.&lt;/span&gt;method&lt;span class=&quot;punctuation punctuation_section punctuation_section_scope punctuation_section_scope_ruby&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;keyword keyword_control keyword_control_ruby&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;keyword keyword_control keyword_control_ruby&quot;&gt;end&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;b&gt;UPDATE:&lt;/b&gt; Here’s a slightly better implementation that allows the .get? and .post? helpers as well as a few other things to work (thanks Chris Nolan for reminding us to update this blog entry):&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;/p&gt;
&lt;pre class=&quot;code&quot;&gt;
ActionController::AbstractRequest.class_eval do
  def request_method_with_facebook_overrides
    @request_method ||= begin
      case
        when parameters[:_method]
          parameters[:_method].downcase.to_sym
        when parameters[:fb_sig_request_method]
          parameters[:fb_sig_request_method].downcase.to_sym
        else
          request_method_without_facebook_overrides
      end
    end
  end
  alias_method_chain :request_method, :facebook_overrides
end
&lt;/pre&gt;
&lt;/div&gt;
</content>
 </entry>
 
 <entry>
   <title>Pretty SVN commit emails</title>
   <link href="http://tech.livingsocial.com/Ops/2007/11/05/pretty-svn-commit-emails.html"/>
   <updated>2007-11-05T00:00:00+00:00</updated>
   <id>http://tech.livingsocial.com/Ops/2007/11/05/pretty-svn-commit-emails</id>
   <content type="html">&lt;div class=&quot;text&quot;&gt;

&lt;p&gt;&lt;img style=&quot;float:left;padding-right:5px&quot; src=&quot;http://blog.hungrymachine.com/assets/2007/11/5/Picture_10_1.png&quot;&gt;&lt;/p&gt;
&lt;p&gt;So i know it may be old school, but I like getting svn commit messages, especially when working on a small team.  I found &lt;a href=&quot;http://elliotth.blogspot.com&quot;&gt;ElliotH’s&lt;/a&gt; post about &lt;a href=&quot;http://elliotth.blogspot.com/2005/02/better-subversion-post-commit-hook.html&quot;&gt;A better subversion post-commit hook than commit-email.pl&lt;/a&gt;, but it wasnt entirely working. &lt;/p&gt;
&lt;p&gt;Most of the credit goes to him, I just fixed the colorization.  &lt;/p&gt;
&lt;p&gt;[UPDATED]: for some reason, new lines werent looking good in all emails&lt;/p&gt;
&lt;pre class=&quot;code&quot;&gt;&lt;span style=&quot;color:#888&quot;&gt;#!/usr/bin/ruby -w&lt;/span&gt;

&lt;span style=&quot;color:#888&quot;&gt;# A Subversion post-commit hook. Edit the configurable stuff below, and&lt;/span&gt;
&lt;span style=&quot;color:#888&quot;&gt;# copy into your repository's hooks/ directory as &quot;post-commit&quot;. Don't&lt;/span&gt;
&lt;span style=&quot;color:#888&quot;&gt;# forget to &quot;chmod a+x post-commit&quot;.&lt;/span&gt;

&lt;span style=&quot;color:#888&quot;&gt;# ------------------------------------------------------------------------&lt;/span&gt;

&lt;span style=&quot;color:#888&quot;&gt;# You *will* need to change these.&lt;/span&gt;

address=&lt;span style=&quot;background-color:#fff0f0&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;FOO@SOME_DOMAIN.com&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
sendmail=&lt;span style=&quot;background-color:#fff0f0&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;/usr/sbin/sendmail&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
svnlook=&lt;span style=&quot;background-color:#fff0f0&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;/usr/bin/svnlook&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;

&lt;span style=&quot;color:#888&quot;&gt;# ------------------------------------------------------------------------&lt;/span&gt;

require &lt;span style=&quot;background-color:#fff0f0&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;'&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;cgi&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;'&lt;/span&gt;&lt;/span&gt;

&lt;span style=&quot;color:#888&quot;&gt;# Subversion's commit-email.pl suggests that svnlook might create files.&lt;/span&gt;
&lt;span style=&quot;color:#036; font-weight:bold&quot;&gt;Dir&lt;/span&gt;.chdir(&lt;span style=&quot;background-color:#fff0f0&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;/tmp&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;)

&lt;span style=&quot;color:#888&quot;&gt;# What revision in what repository?&lt;/span&gt;
repo = &lt;span style=&quot;color:#038; font-weight:bold&quot;&gt;ARGV&lt;/span&gt;.shift()
rev = &lt;span style=&quot;color:#038; font-weight:bold&quot;&gt;ARGV&lt;/span&gt;.shift()

&lt;span style=&quot;color:#888&quot;&gt;# Get the overview information.&lt;/span&gt;
info=&lt;span style=&quot;background-color:#f0fff0&quot;&gt;&lt;span style=&quot;color:#161&quot;&gt;`&lt;/span&gt;&lt;span style=&quot;background-color:#f0fff0&quot;&gt;&lt;span style=&quot;color:#161&quot;&gt;#{&lt;/span&gt;svnlook&lt;span style=&quot;color:#161&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color:#2B2&quot;&gt; info &lt;/span&gt;&lt;span style=&quot;background-color:#f0fff0&quot;&gt;&lt;span style=&quot;color:#161&quot;&gt;#{&lt;/span&gt;repo&lt;span style=&quot;color:#161&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color:#2B2&quot;&gt; -r &lt;/span&gt;&lt;span style=&quot;background-color:#f0fff0&quot;&gt;&lt;span style=&quot;color:#161&quot;&gt;#{&lt;/span&gt;rev&lt;span style=&quot;color:#161&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color:#161&quot;&gt;`&lt;/span&gt;&lt;/span&gt;
info_lines=info.split(&lt;span style=&quot;background-color:#fff0f0&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#04D&quot;&gt;\n&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;)
author=info_lines.shift
date=info_lines.shift
info_lines.shift
comment=info_lines

&lt;span style=&quot;color:#888&quot;&gt;# Output the overview.&lt;/span&gt;
body = &lt;span style=&quot;background-color:#fff0f0&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;&amp;lt;p&amp;gt;&amp;lt;b&amp;gt;&lt;/span&gt;&lt;span style=&quot;background-color:#fff0f0&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;#{&lt;/span&gt;author&lt;span style=&quot;color:#710&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;&amp;lt;/b&amp;gt; &lt;/span&gt;&lt;span style=&quot;background-color:#fff0f0&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;#{&lt;/span&gt;date&lt;span style=&quot;color:#710&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
body &amp;lt;&amp;lt; &lt;span style=&quot;background-color:#fff0f0&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;&amp;lt;p&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
comment.each { |line|  body &amp;lt;&amp;lt; &lt;span style=&quot;background-color:#fff0f0&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;background-color:#fff0f0&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;#{&lt;/span&gt;&lt;span style=&quot;color:#036; font-weight:bold&quot;&gt;CGI&lt;/span&gt;.escapeHTML(line)&lt;span style=&quot;color:#710&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;&amp;lt;br/&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#04D&quot;&gt;\n&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; }
body &amp;lt;&amp;lt; &lt;span style=&quot;background-color:#fff0f0&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
body &amp;lt;&amp;lt; &lt;span style=&quot;background-color:#fff0f0&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;&amp;lt;hr noshade&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;

&lt;span style=&quot;color:#888&quot;&gt;# Get and output the patch.&lt;/span&gt;
changes=&lt;span style=&quot;background-color:#f0fff0&quot;&gt;&lt;span style=&quot;color:#161&quot;&gt;`&lt;/span&gt;&lt;span style=&quot;background-color:#f0fff0&quot;&gt;&lt;span style=&quot;color:#161&quot;&gt;#{&lt;/span&gt;svnlook&lt;span style=&quot;color:#161&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color:#2B2&quot;&gt; diff &lt;/span&gt;&lt;span style=&quot;background-color:#f0fff0&quot;&gt;&lt;span style=&quot;color:#161&quot;&gt;#{&lt;/span&gt;repo&lt;span style=&quot;color:#161&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color:#2B2&quot;&gt; -r &lt;/span&gt;&lt;span style=&quot;background-color:#f0fff0&quot;&gt;&lt;span style=&quot;color:#161&quot;&gt;#{&lt;/span&gt;rev&lt;span style=&quot;color:#161&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color:#161&quot;&gt;`&lt;/span&gt;&lt;/span&gt;
body &amp;lt;&amp;lt; &lt;span style=&quot;background-color:#fff0f0&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;&amp;lt;pre&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
changes.each &lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;do&lt;/span&gt; |top_line|
  top_line.split(&lt;span style=&quot;background-color:#fff0f0&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#04D&quot;&gt;\n&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;).each &lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;do&lt;/span&gt; |line|
    color = &lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;case&lt;/span&gt;
      &lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;when&lt;/span&gt; line =~ &lt;span style=&quot;background-color:#fff0ff&quot;&gt;&lt;span style=&quot;color:#404&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#808&quot;&gt;^Modified: &lt;/span&gt;&lt;span style=&quot;color:#404&quot;&gt;/&lt;/span&gt;&lt;/span&gt; || line =~ &lt;span style=&quot;background-color:#fff0ff&quot;&gt;&lt;span style=&quot;color:#404&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#808&quot;&gt;^=+$&lt;/span&gt;&lt;span style=&quot;color:#404&quot;&gt;/&lt;/span&gt;&lt;/span&gt; || line =~ &lt;span style=&quot;background-color:#fff0ff&quot;&gt;&lt;span style=&quot;color:#404&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#808&quot;&gt;^@@ &lt;/span&gt;&lt;span style=&quot;color:#404&quot;&gt;/&lt;/span&gt;&lt;/span&gt;: &lt;span style=&quot;background-color:#fff0f0&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;gray&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
      &lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;when&lt;/span&gt; line =~ &lt;span style=&quot;background-color:#fff0ff&quot;&gt;&lt;span style=&quot;color:#404&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#808&quot;&gt;^-&lt;/span&gt;&lt;span style=&quot;color:#404&quot;&gt;/&lt;/span&gt;&lt;/span&gt;: &lt;span style=&quot;background-color:#fff0f0&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;red&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
      &lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;when&lt;/span&gt; line =~ &lt;span style=&quot;background-color:#fff0ff&quot;&gt;&lt;span style=&quot;color:#404&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#808&quot;&gt;^&lt;/span&gt;&lt;span style=&quot;color:#04D&quot;&gt;\+&lt;/span&gt;&lt;span style=&quot;color:#404&quot;&gt;/&lt;/span&gt;&lt;/span&gt;: &lt;span style=&quot;background-color:#fff0f0&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;blue&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
      &lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;else&lt;/span&gt; &lt;span style=&quot;background-color:#fff0f0&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;black&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
    &lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;end&lt;/span&gt;
    body &amp;lt;&amp;lt; &lt;span style=&quot;background-color:#fff0f0&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;%Q{&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;&amp;lt;font style=&quot;color:&lt;/span&gt;&lt;span style=&quot;background-color:#fff0f0&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;#{&lt;/span&gt;color&lt;span style=&quot;color:#710&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;&quot;&amp;gt;&lt;/span&gt;&lt;span style=&quot;background-color:#fff0f0&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;#{&lt;/span&gt;&lt;span style=&quot;color:#036; font-weight:bold&quot;&gt;CGI&lt;/span&gt;.escapeHTML(line)&lt;span style=&quot;color:#710&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;&amp;lt;/font&amp;gt;&amp;lt;br/&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#04D&quot;&gt;\n&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
 &lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;end&lt;/span&gt;
&lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;end&lt;/span&gt;
body &amp;lt;&amp;lt; &lt;span style=&quot;background-color:#fff0f0&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;&amp;lt;/pre&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;

&lt;span style=&quot;color:#888&quot;&gt;# Write the header.&lt;/span&gt;
header = &lt;span style=&quot;background-color:#fff0f0&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
header &amp;lt;&amp;lt; &lt;span style=&quot;background-color:#fff0f0&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;To: &lt;/span&gt;&lt;span style=&quot;background-color:#fff0f0&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;#{&lt;/span&gt;address&lt;span style=&quot;color:#710&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color:#04D&quot;&gt;\n&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
header &amp;lt;&amp;lt; &lt;span style=&quot;background-color:#fff0f0&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;From: &lt;/span&gt;&lt;span style=&quot;background-color:#fff0f0&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;#{&lt;/span&gt;address&lt;span style=&quot;color:#710&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color:#04D&quot;&gt;\n&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
header &amp;lt;&amp;lt; &lt;span style=&quot;background-color:#fff0f0&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;Subject: [SVN] &lt;/span&gt;&lt;span style=&quot;background-color:#fff0f0&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;#{&lt;/span&gt;repo&lt;span style=&quot;color:#710&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt; revision &lt;/span&gt;&lt;span style=&quot;background-color:#fff0f0&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;#{&lt;/span&gt;rev&lt;span style=&quot;color:#710&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color:#04D&quot;&gt;\n&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
header &amp;lt;&amp;lt; &lt;span style=&quot;background-color:#fff0f0&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;Reply-to: &lt;/span&gt;&lt;span style=&quot;background-color:#fff0f0&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;#{&lt;/span&gt;address&lt;span style=&quot;color:#710&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color:#04D&quot;&gt;\n&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
header &amp;lt;&amp;lt; &lt;span style=&quot;background-color:#fff0f0&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;MIME-Version: 1.0&lt;/span&gt;&lt;span style=&quot;color:#04D&quot;&gt;\n&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
header &amp;lt;&amp;lt; &lt;span style=&quot;background-color:#fff0f0&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;Content-Type: text/html; charset=UTF-8&lt;/span&gt;&lt;span style=&quot;color:#04D&quot;&gt;\n&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
header &amp;lt;&amp;lt; &lt;span style=&quot;background-color:#fff0f0&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;Content-Transfer-Encoding: 8bit&lt;/span&gt;&lt;span style=&quot;color:#04D&quot;&gt;\n&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
header &amp;lt;&amp;lt; &lt;span style=&quot;background-color:#fff0f0&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#04D&quot;&gt;\n&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;

&lt;span style=&quot;color:#888&quot;&gt;# Send the mail.&lt;/span&gt;
&lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;begin&lt;/span&gt;
    fd = open(&lt;span style=&quot;background-color:#fff0f0&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;|&lt;/span&gt;&lt;span style=&quot;background-color:#fff0f0&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;#{&lt;/span&gt;sendmail&lt;span style=&quot;color:#710&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt; &lt;/span&gt;&lt;span style=&quot;background-color:#fff0f0&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;#{&lt;/span&gt;address&lt;span style=&quot;color:#710&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;, &lt;span style=&quot;background-color:#fff0f0&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;w&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;)
    fd.print(header)
    fd.print(body)
&lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;rescue&lt;/span&gt;
    exit(&lt;span style=&quot;color:#00D; font-weight:bold&quot;&gt;1&lt;/span&gt;)
&lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;end&lt;/span&gt;
fd.close

&lt;span style=&quot;color:#888&quot;&gt;# We're done.&lt;/span&gt;
exit(&lt;span style=&quot;color:#00D; font-weight:bold&quot;&gt;0&lt;/span&gt;)&lt;/pre&gt;
&lt;/div&gt;
</content>
 </entry>
 
 <entry>
   <title>JRuby trunk == better/faster Rails performance</title>
   <link href="http://tech.livingsocial.com/Ruby/2007/11/03/jruby-looking-better-every-day.html"/>
   <updated>2007-11-03T00:00:00+00:00</updated>
   <id>http://tech.livingsocial.com/Ruby/2007/11/03/jruby-looking-better-every-day</id>
   <content type="html">&lt;div class=&quot;text&quot;&gt;
  &lt;p&gt;So I remember a couple months ago playing with JRuby, and while fibonacci was super fast, Rails was way off..  ActiveRecord performance 6x-10x slower than MRI… &lt;/p&gt;
  &lt;p&gt;Looks like its getting better. Disclaimer: These are really really simple non-scientific tests.&lt;/p&gt;
  &lt;p&gt;Local mysql database, MYISAM, table people, with 2 columns, (id, name). 100k rows&lt;/p&gt;
  &lt;pre class=&quot;code&quot;&gt;&amp;gt; jruby -&lt;span style=&quot;color:#036; font-weight:bold&quot;&gt;J&lt;/span&gt;-server -&lt;span style=&quot;color:#036; font-weight:bold&quot;&gt;O&lt;/span&gt; script/console production
  &amp;gt;&amp;gt; &lt;span style=&quot;color:#036; font-weight:bold&quot;&gt;Benchmark&lt;/span&gt;.measure {&lt;span style=&quot;color:#00D; font-weight:bold&quot;&gt;10000&lt;/span&gt;.times {&lt;span style=&quot;color:#036; font-weight:bold&quot;&gt;Person&lt;/span&gt;.find &lt;span style=&quot;color:#A60&quot;&gt;:first&lt;/span&gt;}}.total
  =&amp;gt; &lt;span style=&quot;color:#60E; font-weight:bold&quot;&gt;2.286&lt;/span&gt;&lt;/pre&gt;
  &lt;pre class=&quot;code&quot;&gt;&amp;gt; ./script/console production
  &amp;gt;&amp;gt;  &lt;span style=&quot;color:#036; font-weight:bold&quot;&gt;Benchmark&lt;/span&gt;.measure {&lt;span style=&quot;color:#00D; font-weight:bold&quot;&gt;10000&lt;/span&gt;.times {&lt;span style=&quot;color:#036; font-weight:bold&quot;&gt;Person&lt;/span&gt;.find &lt;span style=&quot;color:#A60&quot;&gt;:first&lt;/span&gt;}}.total
  =&amp;gt; &lt;span style=&quot;color:#60E; font-weight:bold&quot;&gt;1.7&lt;/span&gt;&lt;/pre&gt;
  &lt;pre class=&quot;code&quot;&gt;&lt;span style=&quot;color:#036; font-weight:bold&quot;&gt;Mongrel&lt;/span&gt;
  &amp;gt; ab -n &lt;span style=&quot;color:#00D; font-weight:bold&quot;&gt;1000&lt;/span&gt; http&lt;span style=&quot;color:#A60&quot;&gt;:/&lt;/span&gt;/localhost:&lt;span style=&quot;color:#00D; font-weight:bold&quot;&gt;3001&lt;/span&gt;/people/&lt;span style=&quot;color:#00D; font-weight:bold&quot;&gt;1&lt;/span&gt;
  &lt;span style=&quot;color:#036; font-weight:bold&quot;&gt;Requests&lt;/span&gt; per second:    &lt;span style=&quot;color:#60E; font-weight:bold&quot;&gt;95.02&lt;/span&gt; [&lt;span style=&quot;color:#888&quot;&gt;#/sec] (mean)&lt;/span&gt;&lt;/pre&gt;
  &lt;p&gt;On Glassfish v3 with:  RAILS_ENV=production jruby -J-server -O -S glassfish_rails glass2, after a bit of warmup.&lt;/p&gt;
  &lt;pre class=&quot;code&quot;&gt;&amp;gt; ab -n &lt;span style=&quot;color:#00D; font-weight:bold&quot;&gt;1000&lt;/span&gt; http&lt;span style=&quot;color:#A60&quot;&gt;:/&lt;/span&gt;/localhost:&lt;span style=&quot;color:#00D; font-weight:bold&quot;&gt;8080&lt;/span&gt;/glass2/people/&lt;span style=&quot;color:#00D; font-weight:bold&quot;&gt;1&lt;/span&gt;
  &lt;span style=&quot;color:#036; font-weight:bold&quot;&gt;Requests&lt;/span&gt; per second:    &lt;span style=&quot;color:#60E; font-weight:bold&quot;&gt;48.25&lt;/span&gt; [&lt;span style=&quot;color:#888&quot;&gt;#/sec] (mean)&lt;/span&gt;&lt;/pre&gt;
  &lt;p&gt;turning logging mostly off&lt;/p&gt;
  &lt;pre class=&quot;code&quot;&gt;&amp;gt; ab -n &lt;span style=&quot;color:#00D; font-weight:bold&quot;&gt;1000&lt;/span&gt; http&lt;span style=&quot;color:#A60&quot;&gt;:/&lt;/span&gt;/localhost:&lt;span style=&quot;color:#00D; font-weight:bold&quot;&gt;8080&lt;/span&gt;/glass2/people/&lt;span style=&quot;color:#00D; font-weight:bold&quot;&gt;1&lt;/span&gt;
  &lt;span style=&quot;color:#036; font-weight:bold&quot;&gt;Requests&lt;/span&gt; per second:    &lt;span style=&quot;color:#60E; font-weight:bold&quot;&gt;56.70&lt;/span&gt; [&lt;span style=&quot;color:#888&quot;&gt;#/sec] (mean)&lt;/span&gt;&lt;/pre&gt;
  &lt;p&gt;All in all, thats impressive.  Congrats to Charles, Ola, and the whole JRuby crew.  I dont think i’ll be putting this in production yet, but I’m very interested to hear from others that have.&lt;/p&gt;
&lt;/div&gt;

</content>
 </entry>
 
 <entry>
   <title>Super fast IP to lat/lng in Rails – Part 2</title>
   <link href="http://tech.livingsocial.com/Performance/2007/10/31/super-fast-ip-to-lat-lng-in-rails-part-2.html"/>
   <updated>2007-10-31T00:00:00+00:00</updated>
   <id>http://tech.livingsocial.com/Performance/2007/10/31/super-fast-ip-to-lat-lng-in-rails-part-2</id>
   <content type="html">&lt;div class=&quot;text&quot;&gt;

&lt;p&gt;In  &lt;a href=&quot;http://blog.hungrymachine.com/2007/10/22/super-fast-ip-to-lat-lng-in-rails&quot;&gt;Super fast IP to lat/lng in Rails&lt;/a&gt;, I showed a solution for fast IP to lat/lng resolution in rails.  I called it “Super fast” because it performed orders of magnitude faster the the RESTful interface, but it was also “Super fast” to implement.  That being said, &lt;a href=&quot;http://www.kisscafe.com/&quot;&gt;Kyle&lt;/a&gt; made a comment to check out the GeoIP gem.  I had heard of &lt;a href=&quot;http://www.maxmind.com/&quot;&gt;MaxMind&lt;/a&gt; before, but I didnt want to spend hundreds of dollars to solve this problem.  What I didnt know was they also have a free download of their “lite” datasource.  They have a &lt;a href=&quot;http://www.maxmind.com/app/geolitecountry&quot;&gt;GeoLiteCountry&lt;/a&gt; and &lt;a href=&quot;http://www.maxmind.com/app/geolitecity&quot;&gt;GeoLiteCity&lt;/a&gt; version, although only the City version has lat/lng info.  They provide wrappers in most languages (including Ruby), and while Kyle’s suggested &lt;a href=&quot;http://rubyforge.org/projects/geoip/&quot;&gt;geoip&lt;/a&gt;, I found &lt;a href=&quot;http://rubyforge.org/projects/geoip-city/&quot;&gt;geoip_city&lt;/a&gt; on RubyForge which I like a bit better. &lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;
[UPDATED]: I had forgotten to include the install instructions for getting the GeoIP C library.&lt;/p&gt;
&lt;p&gt;Install the C bindings, the gem (which isnt packaged as a gem for easy download) and get the data.&lt;/p&gt;
&lt;pre class=&quot;code&quot;&gt;wget http&lt;span style=&quot;color:#A60&quot;&gt;:/&lt;/span&gt;/www.maxmind.com/download/geoip/api/c/&lt;span style=&quot;color:#036; font-weight:bold&quot;&gt;GeoIP&lt;/span&gt;.tar.gz
tar -zxvf &lt;span style=&quot;color:#036; font-weight:bold&quot;&gt;GeoIP&lt;/span&gt;.tar.gz
cd &lt;span style=&quot;color:#036; font-weight:bold&quot;&gt;GeoIP&lt;/span&gt;
./configure &amp;amp;&amp;amp; make &amp;amp;&amp;amp; sudo make install

wget http&lt;span style=&quot;color:#A60&quot;&gt;:/&lt;/span&gt;/rubyforge.org/frs/download.php/&lt;span style=&quot;color:#00D; font-weight:bold&quot;&gt;27077&lt;/span&gt;/geoip_city&lt;span style=&quot;color:#60E; font-weight:bold&quot;&gt;-0.1&lt;/span&gt;.gem
sudo gem install geoip_city&lt;span style=&quot;color:#60E; font-weight:bold&quot;&gt;-0.1&lt;/span&gt;.gem
wget http&lt;span style=&quot;color:#A60&quot;&gt;:/&lt;/span&gt;/www.maxmind.com/download/geoip/database/&lt;span style=&quot;color:#036; font-weight:bold&quot;&gt;GeoLiteCity&lt;/span&gt;.dat.gz
gunzip &lt;span style=&quot;color:#036; font-weight:bold&quot;&gt;GeoLiteCity&lt;/span&gt;.dat.gz
sudo mkdir &lt;span style=&quot;background-color:#fff0ff&quot;&gt;&lt;span style=&quot;color:#404&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#808&quot;&gt;usr&lt;/span&gt;&lt;span style=&quot;color:#404&quot;&gt;/&lt;/span&gt;&lt;/span&gt;local/share/&lt;span style=&quot;color:#036; font-weight:bold&quot;&gt;GeoIP&lt;/span&gt;
sudo mv &lt;span style=&quot;color:#036; font-weight:bold&quot;&gt;GeoLiteCity&lt;/span&gt;.dat &lt;span style=&quot;background-color:#fff0ff&quot;&gt;&lt;span style=&quot;color:#404&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#808&quot;&gt;usr&lt;/span&gt;&lt;span style=&quot;color:#404&quot;&gt;/&lt;/span&gt;&lt;/span&gt;local/share/&lt;span style=&quot;color:#036; font-weight:bold&quot;&gt;GeoIP&lt;/span&gt;/&lt;span style=&quot;color:#036; font-weight:bold&quot;&gt;GeoLiteCity&lt;/span&gt;.dat&lt;/pre&gt;
&lt;p&gt;Then the ruby part:&lt;/p&gt;
&lt;pre class=&quot;code&quot;&gt;&amp;gt;&amp;gt; require &lt;span style=&quot;background-color:#fff0f0&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;'&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;geoip_city&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;'&lt;/span&gt;&lt;/span&gt;
&amp;gt;&amp;gt; g = &lt;span style=&quot;color:#036; font-weight:bold&quot;&gt;GeoIPCity&lt;/span&gt;::&lt;span style=&quot;color:#036; font-weight:bold&quot;&gt;Database&lt;/span&gt;.new(&lt;span style=&quot;background-color:#fff0f0&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;'&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;/usr/local/share/GeoIP/GeoLiteCity.dat&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;'&lt;/span&gt;&lt;/span&gt;)
&amp;gt;&amp;gt; res = g.look_up(&lt;span style=&quot;background-color:#fff0f0&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;'&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;4.2.2.2&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;'&lt;/span&gt;&lt;/span&gt;)
&amp;gt;&amp;gt; puts &lt;span style=&quot;background-color:#fff0f0&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;lat: &lt;/span&gt;&lt;span style=&quot;background-color:#fff0f0&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;#{&lt;/span&gt;res[&lt;span style=&quot;color:#A60&quot;&gt;:latitude&lt;/span&gt;]&lt;span style=&quot;color:#710&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt; lng: &lt;/span&gt;&lt;span style=&quot;background-color:#fff0f0&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;#{&lt;/span&gt;res[&lt;span style=&quot;color:#A60&quot;&gt;:longitude&lt;/span&gt;]&lt;span style=&quot;color:#710&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
lat: &lt;span style=&quot;color:#60E; font-weight:bold&quot;&gt;38.0&lt;/span&gt; lng: &lt;span style=&quot;color:#60E; font-weight:bold&quot;&gt;-97.0&lt;/span&gt;&lt;/pre&gt;
&lt;p&gt;So the question is (although its probably obvious), which is faster?&lt;/p&gt;
&lt;pre class=&quot;code&quot;&gt;&amp;gt;&amp;gt;  &lt;span style=&quot;color:#036; font-weight:bold&quot;&gt;Benchmark&lt;/span&gt;.measure { &lt;span style=&quot;color:#00D; font-weight:bold&quot;&gt;1000&lt;/span&gt;.times {&lt;span style=&quot;color:#036; font-weight:bold&quot;&gt;Hostip&lt;/span&gt;.geocode(&lt;span style=&quot;background-color:#fff0f0&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;'&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;4.2.2.2&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;'&lt;/span&gt;&lt;/span&gt;)}}.total
=&amp;gt; &lt;span style=&quot;color:#60E; font-weight:bold&quot;&gt;1.02&lt;/span&gt;
&amp;gt;&amp;gt;   &lt;span style=&quot;color:#036; font-weight:bold&quot;&gt;Benchmark&lt;/span&gt;.measure { &lt;span style=&quot;color:#00D; font-weight:bold&quot;&gt;100000&lt;/span&gt;.times {g.look_up(&lt;span style=&quot;background-color:#fff0f0&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;'&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;4.2.2.2&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;'&lt;/span&gt;&lt;/span&gt;)}}.total
=&amp;gt; &lt;span style=&quot;color:#60E; font-weight:bold&quot;&gt;0.5&lt;/span&gt;&lt;/pre&gt;
&lt;p&gt;Conclusion?  The C library is MUCH faster than my database version.  200k req/s  vs.  1k req/s.  As a side note, I also tested the “geoip” gem, and it was about 3x faster than my database version. &lt;br&gt;&lt;br&gt;&lt;br&gt;
But all in all, for the 5 minutes it took me to write the original version, it was fast enough… but MaxMind GeoLiteCity + the geoip_city gem is Super fast-er.&lt;/p&gt;
&lt;/div&gt;
</content>
 </entry>
 
 <entry>
   <title>OpenSocial is here!</title>
   <link href="http://tech.livingsocial.com/Ops/2007/10/31/opensocial-is-here.html"/>
   <updated>2007-10-31T00:00:00+00:00</updated>
   <id>http://tech.livingsocial.com/Ops/2007/10/31/opensocial-is-here</id>
   <content type="html">&lt;div class=&quot;text&quot;&gt;
  &lt;p&gt;As you may have seen on &lt;a href=&quot;http://www.techcrunch.com/2007/10/30/details-revealed-google-opensocial-to-be-common-apis-for-building-social-apps/&quot;&gt;TechCrunch&lt;/a&gt; and in the &lt;a href=&quot;http://www.nytimes.com/2007/10/31/technology/31google.html?em&amp;amp;ex=1193889600&amp;amp;en=7c3d672decfc4ffc&amp;amp;ei=5087%0A&quot;&gt;New York Times&lt;/a&gt;, Google is days away from the developer launch of Open Social. &lt;/p&gt;
  &lt;p&gt;As a trusted tester/launch partner, we’ve been busy porting our social shopping suite (such as Visual Bookshelf) to OpenSocial.&lt;/p&gt;
  &lt;p&gt;I’ll follow up tomorrow with more thoughts, but I wanted to congratulate the OpenSocial team on the upcoming launch. We’re definitely excited!&lt;/p&gt;
  &lt;p&gt;&lt;img class=&quot;image&quot; src=&quot;http://blog.hungrymachine.com/assets/2007/10/31/orkut-bookshelf.png&quot;&gt;&lt;/p&gt;
&lt;/div&gt;
</content>
 </entry>
 
 <entry>
   <title>Monitoring Rails Apps:  Pulse + More</title>
   <link href="http://tech.livingsocial.com/Rails/2007/10/26/monitoring-rails-apps-pulse-more.html"/>
   <updated>2007-10-26T00:00:00+00:00</updated>
   <id>http://tech.livingsocial.com/Rails/2007/10/26/monitoring-rails-apps-pulse-more</id>
   <content type="html">&lt;div class=&quot;text&quot;&gt;
  &lt;p&gt;&lt;a href=&quot;http://www.pgrs.net/&quot;&gt;Paul Gross&lt;/a&gt; from &lt;a href=&quot;http://www.thoughtworks.com/&quot;&gt;Thoughtworks&lt;/a&gt; recently created a &lt;a href=&quot;http://www.pgrs.net/2007/10/26/announcing-new-gem-pulse&quot;&gt;pulse&lt;/a&gt; gem. The gem adds a simple action to your rails app, “/pulse”, which acts as a heartbeat.&lt;br&gt;&lt;br&gt;&lt;/p&gt;
  &lt;p&gt;The pulse gem currently defines the method as:&lt;/p&gt;
  &lt;pre class=&quot;code&quot;&gt;&lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;def&lt;/span&gt; &lt;span style=&quot;color:#06B; font-weight:bold&quot;&gt;pulse&lt;/span&gt;
     render &lt;span style=&quot;color:#A60&quot;&gt;:text&lt;/span&gt; =&amp;gt; &lt;span style=&quot;background-color:#fff0f0&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;OK&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
  &lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;end&lt;/span&gt;&lt;/pre&gt;
  &lt;p&gt;Then you can configure haproxy to monitor your application by hitting  http://server/pulse and verifying the response is “OK”.&lt;/p&gt;
  &lt;p&gt;We’ve had a similar action in our applications for quite some time, although I really like the idea of externalizing it to a gem.  Our implementation is slightly different though.  Since so many rails applications depend on a database, I instead added:&lt;/p&gt;
  &lt;pre class=&quot;code&quot;&gt;&lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;def&lt;/span&gt; &lt;span style=&quot;color:#06B; font-weight:bold&quot;&gt;pulse&lt;/span&gt;
      rows = &lt;span style=&quot;color:#036; font-weight:bold&quot;&gt;ActiveRecord&lt;/span&gt;::&lt;span style=&quot;color:#036; font-weight:bold&quot;&gt;Base&lt;/span&gt;.connection.execute(&lt;span style=&quot;background-color:#fff0f0&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;select 1 from dual&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;).num_rows &lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;rescue&lt;/span&gt; &lt;span style=&quot;color:#00D; font-weight:bold&quot;&gt;0&lt;/span&gt;
      render &lt;span style=&quot;color:#A60&quot;&gt;:text&lt;/span&gt; =&amp;gt; rows == &lt;span style=&quot;color:#00D; font-weight:bold&quot;&gt;1&lt;/span&gt; ? &lt;span style=&quot;background-color:#fff0f0&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;OK&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; : &lt;span style=&quot;background-color:#fff0f0&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;Error!&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
  &lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;end&lt;/span&gt;&lt;/pre&gt;
  &lt;p&gt;IIRC, “select 1 from dual” is the fastest query you can run against a database, in MySQL, Oracle, and Postgres.  And if you have multiple databases, you can add union in the one pulse request, or have multiple actions.&lt;/p&gt;
  &lt;p&gt;Now you are not only testing your application is live, but that it can connect to the database.&lt;/p&gt;
&lt;/div&gt;
</content>
 </entry>
 
 <entry>
   <title>Super fast IP to lat/lng in Rails</title>
   <link href="http://tech.livingsocial.com/Rails/2007/10/22/super-fast-ip-to-lat-lng-in-rails.html"/>
   <updated>2007-10-22T00:00:00+00:00</updated>
   <id>http://tech.livingsocial.com/Rails/2007/10/22/super-fast-ip-to-lat-lng-in-rails</id>
   <content type="html">   &lt;div class=&quot;text&quot;&gt;
          &lt;p&gt;In building the &lt;a href=&quot;http://blog.hungrymachine.com/2007/10/19/the-importance-of-eye-candy-and-no-not-the-kind-you-re-thinking&quot;&gt;eye candy demo&lt;/a&gt; for the Graphing Social conference, I needed a quick way to geo-locate users by IP address.  For Rails, &lt;a href=&quot;http://geokit.rubyforge.org/&quot;&gt;GeoKit&lt;/a&gt; is an awesome plugin. It supports a list of providers, and overlays distance calculations, before_filter helpers, all sorts of good stuff.&lt;br&gt;&lt;/p&gt;
&lt;p&gt;It uses &lt;a href=&quot;http://www.hostip.info/&quot;&gt;hostip.info&lt;/a&gt; to do IP to lat/lng, using their RESTful interface:&lt;/p&gt;
&lt;pre class=&quot;code&quot;&gt;http&lt;span style=&quot;color:#A60&quot;&gt;:/&lt;/span&gt;/api.hostip.info/get_html.php?ip=&lt;span style=&quot;color:#60E; font-weight:bold&quot;&gt;12.215&lt;/span&gt;.&lt;span style=&quot;color:#60E; font-weight:bold&quot;&gt;42.19&lt;/span&gt;&amp;amp;position=&lt;span style=&quot;color:#038; font-weight:bold&quot;&gt;true&lt;/span&gt;
  &lt;span style=&quot;color:#036; font-weight:bold&quot;&gt;Country&lt;/span&gt;: &lt;span style=&quot;color:#036; font-weight:bold&quot;&gt;UNITED&lt;/span&gt; &lt;span style=&quot;color:#036; font-weight:bold&quot;&gt;STATES&lt;/span&gt; (&lt;span style=&quot;color:#036; font-weight:bold&quot;&gt;US&lt;/span&gt;)
  &lt;span style=&quot;color:#036; font-weight:bold&quot;&gt;City&lt;/span&gt;: &lt;span style=&quot;color:#036; font-weight:bold&quot;&gt;Sugar&lt;/span&gt; &lt;span style=&quot;color:#036; font-weight:bold&quot;&gt;Grove&lt;/span&gt;, &lt;span style=&quot;color:#036; font-weight:bold&quot;&gt;IL&lt;/span&gt;
  &lt;span style=&quot;color:#036; font-weight:bold&quot;&gt;Latitude&lt;/span&gt;: &lt;span style=&quot;color:#60E; font-weight:bold&quot;&gt;41.7696&lt;/span&gt;
  &lt;span style=&quot;color:#036; font-weight:bold&quot;&gt;Longitude&lt;/span&gt;: &lt;span style=&quot;color:#60E; font-weight:bold&quot;&gt;-88.4588&lt;/span&gt;&lt;/pre&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;
This is great, but its just too darn slow to geolocate 12 users a second. All I needed was a FAST ip to lat/long lookup mechanism. Luckily, HostInfo provides the raw data. Here’s how I built super fast GeoLoc by IP method.&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;
Download, create a DB, and import the data.&lt;/p&gt;
&lt;pre class=&quot;code&quot;&gt;wget http&lt;span style=&quot;color:#A60&quot;&gt;:/&lt;/span&gt;/hostip.ww.com/hostip_current.sql.gz
gunzip hostip_current.sql.gz
mysqladmin -uroot create hostip
mysql -uroot hostip &amp;lt; hostip_current.sql&lt;/pre&gt;

Create a simple HostIp class.  Note:  I need to dynamically build this query b/c the data is sharded across tables by the A class of the IP.&lt;/p&gt;
&lt;pre class=&quot;code&quot;&gt;&lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;class&lt;/span&gt; &lt;span style=&quot;color:#B06; font-weight:bold&quot;&gt;Hostip&lt;/span&gt; &amp;lt; &lt;span style=&quot;color:#036; font-weight:bold&quot;&gt;ActiveRecord&lt;/span&gt;::&lt;span style=&quot;color:#036; font-weight:bold&quot;&gt;Base&lt;/span&gt;
  &lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;def&lt;/span&gt; &lt;span style=&quot;color:#038; font-weight:bold&quot;&gt;self&lt;/span&gt;.geocode(ip)
    a,b,c,d = ip.split(&lt;span style=&quot;background-color:#fff0f0&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;)
    &lt;span style=&quot;color:#038; font-weight:bold&quot;&gt;self&lt;/span&gt;.set_table_name &lt;span style=&quot;background-color:#fff0f0&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;hostip.ip4_&lt;/span&gt;&lt;span style=&quot;background-color:#fff0f0&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;#{&lt;/span&gt;a&lt;span style=&quot;color:#710&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
    ip = find(&lt;span style=&quot;color:#A60&quot;&gt;:first&lt;/span&gt;, &lt;span style=&quot;color:#A60&quot;&gt;:select&lt;/span&gt; =&amp;gt; &lt;span style=&quot;background-color:#fff0f0&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;lat,lng&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;,
                &lt;span style=&quot;color:#A60&quot;&gt;:joins&lt;/span&gt; =&amp;gt; &lt;span style=&quot;background-color:#fff0f0&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;%Q{&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;INNER JOIN hostip.cityByCountry
                               ON hostip.ip4_&lt;/span&gt;&lt;span style=&quot;background-color:#fff0f0&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;#{&lt;/span&gt;a&lt;span style=&quot;color:#710&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;.city = hostip.cityByCountry.city
                               AND hostip.ip4_&lt;/span&gt;&lt;span style=&quot;background-color:#fff0f0&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;#{&lt;/span&gt;a&lt;span style=&quot;color:#710&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;.country = hostip.cityByCountry.country&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;}&lt;/span&gt;&lt;/span&gt;,
                &lt;span style=&quot;color:#A60&quot;&gt;:conditions&lt;/span&gt; =&amp;gt; [&lt;span style=&quot;background-color:#fff0f0&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;b = ? and c = ?&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;, b,c])
    &lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;if&lt;/span&gt; ip
      [ip.lat, ip.lng]
    &lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;else&lt;/span&gt;
      [&lt;span style=&quot;background-color:#fff0f0&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;,&lt;span style=&quot;background-color:#fff0f0&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;]
    &lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;end&lt;/span&gt;
  &lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;end&lt;/span&gt;
&lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;end&lt;/span&gt; &lt;/pre&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;/p&gt;
&lt;p&gt;Usage&lt;/p&gt;
&lt;pre class=&quot;code&quot;&gt;&amp;gt;&amp;gt; &lt;span style=&quot;color:#036; font-weight:bold&quot;&gt;Hostip&lt;/span&gt;.geocode(&lt;span style=&quot;background-color:#fff0f0&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;4.2.2.2&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;)
=&amp;gt; [&lt;span style=&quot;background-color:#fff0f0&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;39.944&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;, &lt;span style=&quot;background-color:#fff0f0&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;-105.062&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;]&lt;/pre&gt;


&lt;p&gt;Thats it!  Now you can geolocate by IP in your own datacenter.  &lt;br&gt;&lt;br&gt;
Thanks again to the guys at HostIp for sharing this data!&lt;/p&gt;
&lt;/div&gt;</content>
 </entry>
 
 <entry>
   <title>The Importance of Eye Candy (and no, not the kind you’re thinking)</title>
   <link href="http://tech.livingsocial.com/Biz/2007/10/19/the-importance-of-eye-candy-and-no-not-the-kind-you-re-thinking.html"/>
   <updated>2007-10-19T00:00:00+00:00</updated>
   <id>http://tech.livingsocial.com/Biz/2007/10/19/the-importance-of-eye-candy-and-no-not-the-kind-you-re-thinking</id>
   <content type="html">&lt;div class=&quot;text&quot;&gt;
  &lt;p&gt;We just got back from several conferences around the social media space. CommunityNext was a developer-centric event that allowed for many interactions and trading of best practices with several top Facebook developers. GraphingSocial was a slightly larger gathering that brought together an impressive list of speakers including Reid Hoffman, Michael Arrington, Danny Sullivan and others. It was a great opportunity to network, see some of the latest Facebook applications, and just generally talk shop with investors and developers in the social media space. Sometimes at these events it’s so easy to get lost in the shuffle, that it is tough to talk with the people you want to talk to. We did, however, have what we determined to be a strategic advantage: Eye Candy &lt;/p&gt;

  &lt;p&gt;Here’s how it went down:&lt;/p&gt;

  &lt;p&gt;Step 1: Several weeks before event ~ Randomly sign up for booth and to be a conference sponsor without really having a plan other than “A booth seems like a good idea. We can talk to people. And stuff.”&lt;/p&gt;

  &lt;p&gt;Step 2: 7 days and 3 minutes before event ~ Contemplate whether “Hungry Machine Hula Hoops” send the right message.&lt;/p&gt;

  &lt;p&gt;Step 3: 7 days and 2 minutes before event ~ Return to fetal position in corner &lt;/p&gt;

  &lt;p&gt;Step 4: 3 days before event ~ Eureka! An idea is born. Everybody loves Twittervision and everybody loves money – let’s combine the two! &lt;/p&gt;

  &lt;p&gt;Step 5: 2 days before the event ~ Begin building application that shows the geographic distribution of impressions and clicks within the Hungry Machine ad network (pic below) &lt;/p&gt;

  &lt;p&gt;Step 6: 1 day before event ~ Take break from building application because In &amp;amp; Out Burger is just too damn good.&lt;/p&gt;

  &lt;p&gt;Step 7: Later in that day ~ Eat 3rd double double &lt;/p&gt;

  &lt;p&gt;Step 8: Day of event ~ Deploy application; set up Apple 30 inch monitor that seems to emit a radioactive hue. Notice third arm grow out of small child as he passes monitor &lt;/p&gt;

  &lt;p&gt;Step 9: Booth now open for business! Potential clients, partners and just plain interesting folks start to roll in. They cannot resist the lure that is a 30 inch monitor with people’s heads popping up on a world map.&lt;/p&gt;

  &lt;p&gt;&lt;img class=&quot;image&quot; src=&quot;http://blog.hungrymachine.com/assets/2007/10/19/yamp_1.jpg&quot; alt=&quot;Ad Network Map&quot;&gt;&lt;/p&gt;

  &lt;p&gt;In all seriousness, the above process was only slightly embellished, but really did serve a purpose in how successful and how much we got out of the GraphingSocial conference. Having an initial, built-in talking point is a great way to break the ice with people you are interested in talking with, and generally helps reveal someone’s area of interest within the first minute or two of conversation. We would not have had nearly as successful of a conference without a little extra pizzazz.&lt;/p&gt;
&lt;/div&gt;
</content>
 </entry>
 
 <entry>
   <title>Marketing your Facebook App</title>
   <link href="http://tech.livingsocial.com/Facebook/2007/09/28/marketing-your-facebook-app.html"/>
   <updated>2007-09-28T00:00:00+00:00</updated>
   <id>http://tech.livingsocial.com/Facebook/2007/09/28/marketing-your-facebook-app</id>
   <content type="html">&lt;div class=&quot;text&quot;&gt;
  &lt;p&gt;In the good ol’ days of, let’s say…. three months ago, life was simple. The birds chirped a bit louder, the grass was a little greener, and, best of all, you could build an app on Facebook, submit it to the directory, tag it with a category or two, and see it nestle in among a smattering of other applications and watch your traffic grow at an obscene pace. Those days are over. Kuput. Finito. Building an app on Facebook and letting it “do its thing” is an increasingly difficult, if not impossible thing to do. The good news is that there are a host of traditional and non-traditional ways to gather good, quality traffic for your application. The bad news is that, very likely, it’s going to cost you:&lt;/p&gt;

  &lt;p&gt;Buy an initial seed number of users: If you can generate 10/20/30 thousand users on your app, your installed user base should be large enough at that point in time to see if it sinks or swims. You’ll likely have crossed a wide-demographic range by that point in time and have been able to see if you’ve built your app to properly leverage the viral touch points and social graph.&lt;/p&gt;

  &lt;p&gt;Generate “off-Facebook” buzz: Sure, Facebook pages aren’t crawlable. And sure, your app can’t live outside of Facebook. But that doesn’t mean there isn’t a universe (you know that thing… what’s it called… that’s right, the world wide web) that does still exist outside of Facebook. If you issue a web-based press release, it could get picked up by a variety of news sources who could reference it and Google will definitely crawl it. If you know any bloggers that would have an interest in your application, reach out to them and give them a sneak peak under the hood. If you have an existing destination site, leverage it! 40+ish million people are on Facebook, which means there is a reasonable chance the viewer of your destination site is also a Facebook member.&lt;/p&gt;

  &lt;p&gt;It’s in the name: This is certainly just a hypothesis, but I think a very reasonable one. If someone sends me an app, and I can immediately understand the concept of the app pre-install, I can make a decision point prior to installation about whether or not I think the app would be useful. I may not install it, but at least there is a chance that I will. If I don’t immediately grok how the app will work prior to install, there is no chance I will install it – what is it going to ask of me? Will I have to go out of Facebook to register for a site?&lt;/p&gt;

  &lt;p&gt;Just a few thoughts to consider when figuring out how to make your app go from 0 to 60(thousand users, that is) in 5 seconds flat.&lt;/p&gt;
&lt;/div&gt;
</content>
 </entry>
 
 <entry>
   <title>And so it begins</title>
   <link href="http://tech.livingsocial.com/Uncategorized/2007/08/25/and-so-it-begins.html"/>
   <updated>2007-08-25T00:00:00+00:00</updated>
   <id>http://tech.livingsocial.com/Uncategorized/2007/08/25/and-so-it-begins</id>
   <content type="html">&lt;div class=&quot;text&quot;&gt;

&lt;p&gt;&lt;em&gt;And so it begins&lt;/em&gt;. Welcome to the maiden posting for the Hungry Machine blog. We’re 4 guys bringing our expertise in Ruby On Rails and experience from &lt;a href=&quot;http://aol.com&quot;&gt;&lt;span class=&quot;caps&quot;&gt;AOL&lt;/span&gt;&lt;/a&gt;, &lt;a href=&quot;http://www.revolutionhealth.com/&quot;&gt;Revolution Health&lt;/a&gt;, and &lt;a href=&quot;http://blockbuster.com&quot;&gt;Blockbuster&lt;/a&gt;  together to build some great new products and services. For those of you that read us at &lt;a href=&quot;http://revolutiononrails.blogspot.com&quot;&gt;RevolutionOnRails&lt;/a&gt;, we have a new addition, Tim O’Shaughnessy, who will be handling a bit more of the product-side of the house for us.&lt;/p&gt;
&lt;p&gt;We plan to continue exploring Rails, sharing our expertise with others via this blog and by releasing more plugins, and diving into new areas and applications, ranging from our continued development of Facebook applications to entirely new fields.&lt;/p&gt;
&lt;p&gt;Lastly… why &lt;em&gt;Hungry Machine&lt;/em&gt;? Well, we think it represents our mentality and effort we’ll put into our everyday activities… we’re hungry for success. Check back often to see what we’re up to.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Who we are:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Aaron Batalion&lt;/em&gt;: Aaron has been banging the Rails drum since 2005 and has been deep in the Rails community ever since. A lead portal architect for &lt;a href=&quot;http://www.revolutionhealth.com/&quot;&gt;RevolutionHealth.com&lt;/a&gt;, Aaron was also a portal architect for &lt;a href=&quot;http://blockbuster.com&quot;&gt;Blockbuster.com&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Eddie Frederick&lt;/em&gt;: Eddie was a RoR lead at Revolution Health and has become one of the leading developers in the &lt;a href=&quot;http://facebook.com&quot;&gt;Facebook&lt;/a&gt; space, authoring applications with well over 1M users. He specializes in creating end-to-end user experiences from deployment to application UI.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Tim O’Shaughnessy&lt;/em&gt;: An entrepreneur at heart, Tim led the Product Development Department – Consumer Products at Revolution Health before helping found Hungry Machine. Tim also has has launched successful products at &lt;span class=&quot;caps&quot;&gt;AOL&lt;/span&gt; and enjoys long walks on the beach.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Val Aleksenko&lt;/em&gt;: Val brings over 17 years of software development experience to Hungry Machine. Val’s like MacGyver but with software; give him a stack, a deployment script, and a Red Bull and watch him go.&lt;/p&gt;

&lt;/div&gt;
</content>
 </entry>
 
 <entry>
   <title>Reconfiguring the whole rails stack via a central YAML file</title>
   <link href="http://tech.livingsocial.com/Rails/2007/08/20/reconfiguring-the-whole-rails-stack-via-a-central-yaml-file.html"/>
   <updated>2007-08-20T00:00:00+00:00</updated>
   <id>http://tech.livingsocial.com/Rails/2007/08/20/reconfiguring-the-whole-rails-stack-via-a-central-yaml-file</id>
   <content type="html">&lt;div class=&quot;text&quot;&gt;
          &lt;p&gt;The challenge with hosting of multiple Rails-based Facebook applications is that the amount of users grow quickly. To address this problem we are using &lt;span class=&quot;caps&quot;&gt;EC2&lt;/span&gt; nodes that we can expand/shrink as the demand grows. The price/performance ratio isn’t quite what we first expected, so we are moving toward having a few dedicated boxes instead. Another problem that we add at least a couple of applications a week. On each box that hosts them, we need to reconfigure monit, haproxy, nginx, logrotate and nagios.&lt;/p&gt;
&lt;p&gt;To mitigate both issues on dedicated boxes, we resolved to have a central configuration definition in svn with individual box configurations keyed on localhost name. A ruby script regenerates all those aforementioned configuration files from &lt;span class=&quot;caps&quot;&gt;ERB&lt;/span&gt;-processed templates when it is run on a box and bounces the services. A sample config looks like:&lt;/p&gt;
&lt;pre class=&quot;code&quot;&gt;dedicated&lt;span style=&quot;color:#00D; font-weight:bold&quot;&gt;-1&lt;/span&gt;:

    description: &lt;span style=&quot;background-color:#fff0f0&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;The dedicated box #1&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
    ip: &lt;span style=&quot;color:#60E; font-weight:bold&quot;&gt;64.233&lt;/span&gt;.&lt;span style=&quot;color:#60E; font-weight:bold&quot;&gt;167.99&lt;/span&gt;
    failover: dedicated&lt;span style=&quot;color:#00D; font-weight:bold&quot;&gt;-2&lt;/span&gt;

    apps:

        bookshelf:
            port: &lt;span style=&quot;color:#00D; font-weight:bold&quot;&gt;5000&lt;/span&gt;
            instances: &lt;span style=&quot;color:#00D; font-weight:bold&quot;&gt;20&lt;/span&gt;
            response: &lt;span style=&quot;color:#036; font-weight:bold&quot;&gt;Book&lt;/span&gt;

        ljconnect:
            port: &lt;span style=&quot;color:#00D; font-weight:bold&quot;&gt;6000&lt;/span&gt;
            instances: &lt;span style=&quot;color:#00D; font-weight:bold&quot;&gt;7&lt;/span&gt;
            virtual: ljconnect.hungrymachine.com
            response: &lt;span style=&quot;color:#036; font-weight:bold&quot;&gt;Journal&lt;/span&gt;
                      &lt;/pre&gt;
&lt;p&gt;That definition would generate a monit config with 20 instances of the &lt;em&gt;bookshelf&lt;/em&gt; application and 7 instances of the &lt;em&gt;ljconnect&lt;/em&gt; application plus all other configurations (including nagios health checks expecting the &lt;em&gt;response&lt;/em&gt; value) . It is all possible because we adopt a fixed application deployment file structure and port numbering conventions (via offsets) for all servers.&lt;/p&gt;
&lt;/div&gt;
</content>
 </entry>
 
 <entry>
   <title>Using a ruby-based AIM notifier in nagios</title>
   <link href="http://tech.livingsocial.com/Ruby/2007/08/14/using-a-ruby-based-aim-notifier-in-nagios.html"/>
   <updated>2007-08-14T00:00:00+00:00</updated>
   <id>http://tech.livingsocial.com/Ruby/2007/08/14/using-a-ruby-based-aim-notifier-in-nagios</id>
   <content type="html">      &lt;div class=&quot;text&quot;&gt;
          &lt;p&gt;If you use &lt;a href=&quot;http://www.nagios.org/&quot;&gt;nagios&lt;/a&gt; for monitoring of your rails instances, you might want to get notification not only via email or &lt;a href=&quot;http://www.sms411.net/2006/07/how-to-send-email-to-phone.html&quot;&gt;&lt;span class=&quot;caps&quot;&gt;SMS&lt;/span&gt;-messages&lt;/a&gt; but to your &lt;span class=&quot;caps&quot;&gt;AIM&lt;/span&gt; when you are online. The script (&lt;em&gt;libexec/aim_notifier.rb&lt;/em&gt;) utilizes the &lt;a href=&quot;http://rubyforge.org/projects/net-toc/&quot;&gt;Net::TOC&lt;/a&gt; gem for sending out notifications:&lt;/p&gt;

&lt;pre class=&quot;code&quot;&gt;&lt;span style=&quot;color:#888&quot;&gt;#!/usr/bin/env ruby&lt;/span&gt;

 require &lt;span style=&quot;background-color:#fff0f0&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;'&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;rubygems&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;'&lt;/span&gt;&lt;/span&gt;
 require &lt;span style=&quot;background-color:#fff0f0&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;'&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;net/toc&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;'&lt;/span&gt;&lt;/span&gt;

 user = &lt;span style=&quot;background-color:#fff0f0&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;'&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;your_bot_name&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;'&lt;/span&gt;&lt;/span&gt;
 password = &lt;span style=&quot;background-color:#fff0f0&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;'&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;bot_password&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;'&lt;/span&gt;&lt;/span&gt;

 msg = &lt;span style=&quot;color:#038; font-weight:bold&quot;&gt;ARGV&lt;/span&gt;[&lt;span style=&quot;color:#00D; font-weight:bold&quot;&gt;0&lt;/span&gt;].to_s.gsub(&lt;span style=&quot;background-color:#fff0f0&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;'&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;\n&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;'&lt;/span&gt;&lt;/span&gt;, &lt;span style=&quot;background-color:#fff0f0&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#04D&quot;&gt;\n&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;)

 client = &lt;span style=&quot;color:#036; font-weight:bold&quot;&gt;Net&lt;/span&gt;::&lt;span style=&quot;color:#036; font-weight:bold&quot;&gt;TOC&lt;/span&gt;.new(user, password)

 client.connect

 sleep &lt;span style=&quot;color:#00D; font-weight:bold&quot;&gt;3&lt;/span&gt;

 buddies = []

 client.buddy_list.each_group { |g, b| buddies = b &lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;if&lt;/span&gt; g == &lt;span style=&quot;background-color:#fff0f0&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;'&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;Friends&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;'&lt;/span&gt;&lt;/span&gt; }

 buddies.each &lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;do&lt;/span&gt; |b|
   b.send_im(msg) &lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;if&lt;/span&gt; b.available?
 &lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;end&lt;/span&gt;

 sleep &lt;span style=&quot;color:#00D; font-weight:bold&quot;&gt;3&lt;/span&gt;

 client.disconnect&lt;/pre&gt;

&lt;p&gt; You need to add any account you want to be notified to bot’s friends (either by logging to &lt;span class=&quot;caps&quot;&gt;AIM&lt;/span&gt; using the bot account or using Net::TOC’s ability to add friends).&lt;/p&gt;
&lt;p&gt; The last piece is to add a new notifier in &lt;em&gt;etc/objects/commands.cfg&lt;/em&gt; as:&lt;/p&gt;

&lt;pre class=&quot;code&quot;&gt; define command{
         command_name    notify-service-by-aim
         command_line    $USER1$/aim_notifier.rb $ARG1$ $ARG2$ &quot;***** Nagios *****\n\nNotification Ty
 pe: $NOTIFICATIONTYPE$\n\nService: $SERVICEDESC$\nHost: $HOSTALIAS$\nAddress: $HOSTADDRESS$\nState:
 $SERVICESTATE$\n\nDate/Time: $LONGDATETIME$\n\nAdditional Info:\n\n$SERVICEOUTPUT$&quot;
         }&lt;/pre&gt;

&lt;p&gt; and to append it to the list of notifiers defined for a contact template in &lt;em&gt;etc/objects/commands.cfg&lt;/em&gt;:&lt;/p&gt;

&lt;pre class=&quot;code&quot;&gt; service_notification_commands   notify-service-by-email,notify-service-by-aim&lt;/pre&gt;

&lt;p&gt;Repeat the configuration if you want to use the &lt;span class=&quot;caps&quot;&gt;AIM&lt;/span&gt; notification for hosts as well.&lt;/p&gt;
&lt;/div&gt;
</content>
 </entry>
 
 <entry>
   <title>Routing to the initial action after facebook application install</title>
   <link href="http://tech.livingsocial.com/Facebook/2007/08/14/routing-to-the-initial-action-after-facebook-application-install.html"/>
   <updated>2007-08-14T00:00:00+00:00</updated>
   <id>http://tech.livingsocial.com/Facebook/2007/08/14/routing-to-the-initial-action-after-facebook-application-install</id>
   <content type="html">  &lt;div class=&quot;text&quot;&gt;
          &lt;p&gt;Some facebook applications might have multiple entries. For example, a user might be adding an application (action – &lt;em&gt;new&lt;/em&gt;) or replying to an invitation (action – &lt;em&gt;reply&lt;/em&gt;, param – &lt;em&gt;id&lt;/em&gt;). Since the UI for Facebook application configuration allows to provide only static &lt;em&gt;Post-Add &lt;span class=&quot;caps&quot;&gt;URL&lt;/span&gt;&lt;/em&gt; it might seem like there is no way to route users back to the original action if they tried to reach when the application has not been installed for them. Luckily, we have full control on the destination via the &lt;em&gt;next&lt;/em&gt; paramater of the post install &lt;span class=&quot;caps&quot;&gt;URL&lt;/span&gt;. All we need is to build a &lt;span class=&quot;caps&quot;&gt;URL&lt;/span&gt; using the incoming call parameters with the exclusion of Facebook-specific ones.&lt;/p&gt;
&lt;p&gt;This is an example for &lt;a href=&quot;http://code.google.com/p/facebook-rails/&quot;&gt;Facebook on Rails&lt;/a&gt; based code that might go to the application controller:&lt;/p&gt;

&lt;pre class=&quot;code&quot;&gt;&lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;class&lt;/span&gt; &lt;span style=&quot;color:#B06; font-weight:bold&quot;&gt;ApplicationController&lt;/span&gt; &amp;lt; &lt;span style=&quot;color:#036; font-weight:bold&quot;&gt;Facebook&lt;/span&gt;::&lt;span style=&quot;color:#036; font-weight:bold&quot;&gt;FBMLController&lt;/span&gt;

protected

  before_filter &lt;span style=&quot;color:#A60&quot;&gt;:require_facebook_install&lt;/span&gt;

  &lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;def&lt;/span&gt; &lt;span style=&quot;color:#06B; font-weight:bold&quot;&gt;require_facebook_install&lt;/span&gt;
    &lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;if&lt;/span&gt; in_canvas? &amp;amp;&amp;amp; !fbsession.is_valid?
      redirect_to fbsession.get_install_url(&lt;span style=&quot;color:#A60&quot;&gt;:next&lt;/span&gt; =&amp;gt; url_for(post_install_params))
      &lt;span style=&quot;color:#038; font-weight:bold&quot;&gt;false&lt;/span&gt;
    &lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;end&lt;/span&gt;
  &lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;end&lt;/span&gt;

  &lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;def&lt;/span&gt; &lt;span style=&quot;color:#06B; font-weight:bold&quot;&gt;post_install_params&lt;/span&gt;
    params.merge(&lt;span style=&quot;color:#A60&quot;&gt;:init&lt;/span&gt; =&amp;gt; &lt;span style=&quot;color:#038; font-weight:bold&quot;&gt;true&lt;/span&gt;).delete_if { |k, v| k.starts_with?(&lt;span style=&quot;background-color:#fff0f0&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;'&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;fb_sig&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;'&lt;/span&gt;&lt;/span&gt;) }
  &lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;end&lt;/span&gt;

&lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;end&lt;/span&gt;&lt;/pre&gt;


&lt;p&gt;Notice that the code sets the &lt;em&gt;init&lt;/em&gt; parameter so it &lt;a href=&quot;indentifying-users-who-just-installed-your-facebook-apps&quot;&gt;can be used to identify a post install call&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
</content>
 </entry>
 
 <entry>
   <title>Indentifying users who just installed your facebook apps</title>
   <link href="http://tech.livingsocial.com/Facebook/2007/08/14/indentifying-users-who-just-installed-your-facebook-apps.html"/>
   <updated>2007-08-14T00:00:00+00:00</updated>
   <id>http://tech.livingsocial.com/Facebook/2007/08/14/indentifying-users-who-just-installed-your-facebook-apps</id>
   <content type="html">&lt;div class=&quot;text&quot;&gt;

&lt;p&gt;Sometimes it is useful to do some action on a Facebook user right after your application has been installed by the user. For example, you might want to push some default

&lt;span class=&quot;caps&quot;&gt;FBML&lt;/span&gt; to user’s profile in case he does not complete the action you expect him to do after installation. Facebook application configuration allows to provide

&lt;em&gt;Post-Add &lt;span class=&quot;caps&quot;&gt;URL&lt;/span&gt;&lt;/em&gt; to route users to the destination url after the application install. It could be a dedicated &lt;em&gt;post_add&lt;/em&gt; action or, in case of a default action where you have some code in the controller and since Facebook limits amount of redirects you can use, it could be a parameter to the url, like &lt;code&gt;&amp;amp;init=true&lt;/code&gt;, used to identify that it was a post-install action and execute on it.&lt;/p&gt;
&lt;/div&gt;
</content>
 </entry>
 
 
</feed>
