New in Rails: ActiveResource timeouts and why it matters

If you’ve ever used ActiveResource or for that matter, coded anything that involves interacting with a remote API, you’ve probably had the misfortune of having that API go down or become unresponsive. The experienced old geezers would already have forseen the problem and set a timeout on those API calls. For the rest of us, it’s a good time to get acquainted with the idea of fail-fast and how no response is better than a slow response.

So what happens when the API you’re accessing via ActiveResource or Net::HTTP (or whatever, really, so long as there’s a network socket involved!) becomes unresponsive?

Unfettered outbound remote connections can kill your server

ActiveResource (or Net::HTTP or whatever you’re using) would block while waiting for the API to return. What did we learn about blocking IO in Operating Systems 101? That your process or thread gets stuck waiting for a response that’s what. So now your Mongrel/Thin/Ebb/X web server process basically stuck waiting for a response from an API that might return a response in 30 seconds, or maybe it’ll never return at all. It won’t be long before all your web server processes get blocked and its time to “kill dash nine” (kill -9) some processes and bring out the 500 error page. Yes, your server has been incapacitated and your website is now basically offline.

im in ur serverz making thingz better


Timeouts and you

If you’re using Net::HTTP you can easily safeguard yourself against errors like this by setting a timeout on the socket connection. Like so:

def fetch_something_from_some_api(uri)
  http = Net::HTTP.new(uri.host, uri.port)
  http.read_timeout = timeout

  response = http.start { http.request(Net::HTTP::Get.new("#{uri.path}?#{uri.query}")) }
  response.is_a?(Net::HTTPSuccess) ? do_something_with(response.body) : nil
rescue Timeout::Error
  logger.warn("Timeout accessing #{uri}: #{$!}")
  nil
rescue
  logger.warn("Error accessing #{uri}: #{$!}")
  nil
end

Take note that you really do need to explicitly rescue from the Timeout::Error (or Interrupt) since it’s a child of the Interrupt class and not a StandardError.

Any good client library should also allow you to specify a timeout on the socket connection so read the API documentation.

So what’s this about ActiveResource?

So back to ActiveResource: Michael Koziarski was kind enough to commit my 2 patches (this and this) to ActiveResource so now on edge Rails, you can do this:

class Person < ActiveResource::Base
  self.site = 'http://api.people.com:3000/'
  self.timeout = 5
end

This sets the timeout to 5 seconds on the underlying Net::HTTP instance that ActiveResource uses. The default timeout (to be exact, the read_timeout) for Net::HTTP is 60 seconds on most Ruby implementations (that includes MRI). That’s far too long if your ActiveResource call is in a public-facing controller!

If you are using ActiveResource anywhere and haven’t safeguarded your application with a timeout, I think it’s a good idea to fix it by using edge Rails or at least applying the patch!

The 2nd ActiveResource patch introduces the ActiveResource::TimeoutError exception that you should rescue from whenever you make an ActiveResource call. When this happens, it’s up to your application to decide what to do (like show a placating we’re sorry message). At least your application is still able to do something!

Generating migrations gets easier - Rails 2.0 a feature a day #6

You may not have noticed this yet, but Rails 2.0 has a new convenient syntax for generating ActiveRecord migrations. Go ahead, run the migration generator with script/generate migration. I’ll wait.

Yup, you can now specify the columns you want to add in your migration by passing attribute/type pairs to the migration generator. Ergo,

script/generate migration AddMoreToAnime episodes:integer licensed:boolean

will generate a migration like so:

class AddMoreToAnime < ActiveRecord::Migration
  def self.up
    add_column :animes, :episodes, :integer
    add_column :animes, :licensed, :boolean
  end

  def self.down
    remove_column :animes, :licensed
    remove_column :animes, :episodes
  end
end

This ties in pretty nicely with the syntax for the model generator (script/generate model), which also accepts attribute pairs. Tiny change but “it’s all about consistency”.

For the geeks among you, check out the related changeset and ticket.

About the contributor, Pratik Naik

Pratik Naik (WorkingWithRails profile), probably better known as lifofifo or just lifo, is an active Rails contributor and can be found on #rails-contrib and #rubyonrails nearly 24/7. Almost everyone who’s used Rails has used code that lifo has written. Oh, and lifo also won one of the monthly Rails Hackfests.

He also keeps a pretty good blog where he posts mostly on Rails hacking and tips.

Concatenate your stylesheets and JavaScripts in 3 seconds - Rails 2.0 a feature a day #3

I don’t think I need to explain how concatenating your 5 stylesheets and 12 JavaScript files into single files each makes your webpages load faster. Unless you’re using multiple asset hosts (Rails 2 allows for multiple asset hosts), then it becomes tricky to say for sure which method is better, but I digress.

There’re a bunch of really useful plugins that help you bundle your JS and CSS files, most of them offering minifying/packing of JS and stripping of comments and whitespace in CSS as well. I was a big fan (still love it) of Asset Packager, but newer plugins like PackR and Bundle-fu work great too.

With Rails 2.0 though, unless you want the minifying/packing/comment-stripping features, you can do away with installing a packager plugin. Remember your trusty javascript_include_tag and stylesheet_link_tag? They now accept a :cache option:

# :cache => true creates a cached javascript named all.js.
<%= javascript_include_tag :all, :cache => true %>
# This becomes:
# <script type="text/javascript" src="/javascripts/all.js"></script>

# You can name your javascript too, by passing a name instead of true.
<%= javascript_include_tag 'jquery', 'swfobject', 'application', :cache => 'base' %>
# This becomes:
# <script type="text/javascript" src="/javascripts/base.js"></script>

# Same deal for stylesheets...
# :cache => true creates a stylesheet named all.css.
<%= stylesheet_link_tag :all, :cache => true %>
# This becomes:
# <link href="/stylesheets/all.css"  media="screen" rel="Stylesheet" type="text/css" />

# You can name your stylesheet like for javascript_include_tag.
<%= stylesheet_link_tag 'yui/reset-fonts-grids', 'application', :cache => 'styles' %>
# This becomes:
# <link href="/stylesheets/styles.css"  media="screen" rel="Stylesheet" type="text/css" />

Of course, this only takes place if caching is turned on (ActionController::Base.perform_caching), which is on by default in the production environment and off in the development environment.

For those who want to look at some code, check out the changeset.

About the contributor, DHH

Well, DHH hardly needs any mention. David has_one Wikipedia entry. Nice little touch on this new feature though, I love the convenience.

I promise, like I’d said before, to cover contributions by someone less “mainstream” in the next Rails 2 “feature a day” blog post.

Firefox 3, Beta

Firefox 3 Beta 1 is out! Check out the pretty sweet list of changes.


If you want to try it, you’ll probably want to run Firefox 3 and Firefox 2 at the same time. Only this time you should remember to rename Firefox 3 so that it doesn’t override your install of Firefox 2.

I’d blogged about some of the changes previously if you care for some screenshots of some of the new features (Mozilla Links covers a good number of new Firefox 3 changes too):

New in Rails: a request profiler for profiling your app

Jeremy Kemper (aka bitsweat) committed a very useful tool into the Rails trunk not too long ago: a request profiler! It’s a human-friendly wrapper script around the ruby-prof library, a nice ruby code profiler, that lets you run multiple requests against a URI in your application and get a detailed code profile report in text and HTML.

Wanna try it out? Update your vendor/rails to at least revision 8016, run rake rails:update to copy the new script/performance/request script into your app’s script directory, install the ruby-prof gem (sudo gem install ruby-prof), then let it loose on your app.

The options are pretty simple, just pass the script the URI you wanna profile. There’re options for specifying how many requests you want to process, and for profiling POST requests, there’s one for
specifying a POST fixture file.

USAGE: script/performance/request uri [options]
    -u, --uri [URI]                  Request URI. Defaults to http://localhost:3000/
    -n, --times [0000]               How many requests to process. Defaults to 1000.
    -b, --benchmark                  Benchmark instead of profiling
        --method [GET]               HTTP request method. Defaults to GET.
        --fixture [FILE]             Path to POST fixture file
        --open [CMD]                 Command to open profile results. Defaults to "open %s &"
    -h, --help                       Show this help

At the end of the run, you get a text and HTML report with the methods called and the time spent in them. If you haven’t seen a code profile before, it looks something like this:

Rails request profiler text output report


Very nice stuff! It’s extremely convenient to have profiling like this built into Rails itself - personally I’ve not even run any profiling on my Rails code because it seemed like a hassle (though I do run httperf benchmarks and take note the number of requests per second). With code profiling, you can easily see which parts of your code are the bottlenecks and optimize away - it’s a godsend that it’s so easy to do it in Rails!

Anyway, this is all still new stuff I imagine and subject to change (and improvements), but still very exciting for those of us who are hitting performance bottlenecks in our Rails apps (and are not already doing code profiling).