Wednesday, February 17, 2010

Using Ruby's Queue class to manage inter-thread communication

Bob Potter just showed me an awesome way to use Ruby's Queue class to communicate between two threads. I try to avoid multi-threaded programming as much as possible since I don't feel super confident with concurrency (at least with a language like Ruby). It can add a lot of complexity and headaches even when you know what you're doing, but there are several cases in OtherInbox where it makes a lot of sense.

In this case, I needed to log a very frequently-occurring event to SimpleDB. We don't need these logs to be 100% accurate, and the data gets processed offline for reports, so there's no need to keep the data in our main relational database. My first naive version of this code pushed a new item to SimpleDB each time the event occurred, but this ended up chewing up a lot of memory. To avoid slowing down the main process, I had been handing these one-off SimpleDB calls to an EventMachine deferred block, which caused references to all the objects I was using to generate the SimpleDB items to stick around for too long.

That's when Bob suggested I use a Queue to batch the work into chunks of 25 (the SimpleDB BatchPutAttribute limit) onto a separate standard Ruby thread. The resulting code looks like this (simplified for readability):
class Tracker
def track_event(a,b,c)
@queue ||= Queue.new
start_pushing_thread
hash = { :a => a, :b =>, :c => c }
@queue << hash
end

private

def start_pushing_thread
return if @pushing_thread
@pushing_thread = Thread.new do
items = []

loop do
# pop will block until there are queue items available
items << @queue.pop

if items.size > 24
SdbWrapper::batch_log_to_sdb(items,'tracking_domain')
items.clear
end
end
end
end

end

Once more than 24 items are in the queue, the thread calls code that we wrote to handle batch puts, then clears the array and waits for more.

We use an inter-process/inter-machine version of this paradigm all the time at OtherInbox: we make heavy use of SQS queues to handoff work from one box to another, but that wouldn't have helped here because then we'd just be introducing yet another web service dependency. So if you're in a situation where you need to keep a high volume process running quickly while handing off less important work in chunks, check out Queues!

Monday, January 18, 2010

Ruby for Startups at Lone Star Ruby Conference 2009

Recently Confreaks posted video from the Lone Star Ruby Conference talk I gave in August, called Ruby for Startups.

I've refined the talk a few times since then but it's still a good representation of my current state of mind about what I've learned about Ruby and about software design while building OtherInbox. Check it out if you'd like to see more! The slides are posted here.


Wednesday, November 11, 2009

Lean startup tools for Rails apps

A few months ago I was invited to dinner with the Geeks on a Plane crew when they stopped in Washington, and had the opportunity to meet one of my heroes, Eric Ries, author of the Startup Lessons Learned blog. His descriptions of lean startup techniques and philosophies have had a big influence on the way I design and build software.

Eric asked me what specific tools Rails developers could use when building a lean startup. Here's a revised version of what I emailed in response, garnered while building OtherInbox and other Rails apps:
  • First and foremost, I find Rails itself to be very useful for building a product for a lean startup; the expressiveness of Ruby and the conventions of Rails help developers more quickly build a minimum viable product. I'm still able to surprise people who have worked with me for awhile with how quickly I can turn their feature ideas into
    something they can play with and show customers.

  • For continuous integration, like many Rails shops, we use CruiseControl.rb - it's easy to install and customize, but I don't think people are especially enamored of it. But it works. Two very promising alternatives to rolling your own CI server are Devver and RunCodeRun. I've tried both but our app has grown too complex for either of them (we use a lot of gems and have a pretty customized test environment). For Github users, RunCodeRun exposes a post-commit hook so the tests run automatically after every commit which is pretty useful.

  • Speaking of Github, I'd love for them to implement pre-commit hooks, because then you could prevent developers from making commits any time the build is broken, which prevents people from ignoring problems in a large code base and just tunneling on building their one little feature. Right now if you want to implement this, you need to setup your own source control repository that can talk to the continuous integration system.

  • To monitor exceptions, we use the excellent Hoptoad app. This tool adds a lot of context to bug discussions, because nonprogrammers can reference the exact Hoptoad URL containing all of the information a programmer needs to fix a bug (including backtraces). Because it has an RSS feed, one could also use "Unresolved Hoptoad Errors" as a metric influencing the continuous deployment system. If a release goes out and suddenly there are new errors, that's a sign that the batch was bad and needs to be reverted. There's a drop-in Rails plugin but this service could be used with any language.

  • There are two A/B testing plugins for Rails: 7 Minute ABs and A/Bingo. I haven't used either and am not sure there are any better than rolling your own. Update: Charlie Park in the comments mentions the new plugin Vanity which came out just after I wrote this.

  • There are several good unit testing frameworks for Rails, each with their own devotees. What comes with Ruby and Rails is plenty good enough but some people like the greater expressiveness afforded by things like Rspec and Shoulda. For my next product I'd like to try Shoulda because it uses Ruby's built-in test facilities (making for one less dependency to worry about, as is the case with Rspec) and because I really like the examples I've seen on the Thoughtbot blog.

  • We love Cucumber for higher level testing. When coupled with Webrat, which simulates a real browser, you get a pretty nice mechanism for exercising the entire app in a test environment before deployment. Webrat even has a Selenium adapter, so you actually can run your tests inside of a browser to make sure all is well before deploying a change.

  • This isn't Rails-specific, but we use SimpleDB for dumping a lot of important metrics data, like performance measurements, which we then turn into metrics. This keeps us from having to hit our database too much. The RightAWS gem makes interacting with SimpleDB pretty easy.

  • For our metrics we mainly use Graphite, the graphing and analysis system open-sourced last year by Orbitz. Our whole team is falling more in love with it every day.

  • New Relic has a nice plugin for Rails that reports all kinds of useful data to their service, which could become part of a cluster immune system for Rails apps. They measure average responsiveness and compute an aggregate statistic called Apdex which can be a good indicator of site health (at minimum, any significant changes to Apdex should be investigated, and they will email you alerts about such changes).

  • Capistrano is still the standard way most developers are deploying Rails apps (but also check out Vlad the Deployer), but I think there's an opportunity for someone to build a Ruby library to facilitate continuous deployment that would work better than Capistrano. It would definitely be built using Rake like Vlad does.

  • Update: I haven't used Heroku, but as Ryan points out in the comments it definitely belongs on this list as a compelling, get-up-and-running fast deployment platform.

Wednesday, September 30, 2009

Steal my ideas for Baltimore's tech culture!

Gus Sentementes was nice enough to go on vacation and let a group of guest authors contribute to his excellent blog, BaltTech. My first post just went up, a list of ideas that I think would be cool to implement in Baltimore to further advance our tech culture.

My favorite idea from the list, mostly because I think it's one of the easiest and one of the highest yield, sprung from an earlier post of mine surveying technologists in Baltimore:
Breakfast events: there's a lot going on at night in our tech culture; how about doing things in the morning? I'd love to get a "software breakfast" going where developers could get together and show off their work, exchange war stories, etc.

Friday, August 28, 2009

Ruby for Startups Talk at Lone Star Ruby Conference

Today I gave a talk about my experiences writing the code for OtherInbox, called Ruby for Startups. The slides are below. Hope you find them interesting!

The design principals from the first slide come from Russ Olsen's book, Design Patterns in Ruby (and originally from Design Patterns: Elements of Reusable Object-Oriented Software).

Saturday, August 22, 2009

Vote up JavaScript talks for SXSW 2010

Attending JSConf 2009 was a real eye-opener for me: there are a lot of people using JavaScript in really interesting ways to do phenomenal things inside and outside of the browser. Projects like Phonegap, Titanium, CouchDB, SproutCore, and Cappuccino have the potential to transform many aspects of computing or at least point the way to some new paradigms.

To keep the conversation going, this led me to propose one talk and one panel for SXSW 2010:

Building Rich Web Apps with SproutCore
The JavaScript Applications Renaissance

If those sound intriguing, please consider voting at the above links, or better yet leave a comment expressing your support.

There are several other JavaScript related talks that I hope you will check out as well:

http://panelpicker.sxsw.com/ideas/index/4/q:javascript