Photo-1 Photo-2 Photo-3 Photo-4 Photo-5 Photo-6

@brentmc79

@brentmc79

Full-time web developer. Part-time smart ass.

I'm Brent Collier.

After a year and a half as an engineer on Twitter's Trust & Safety team, I'm looking for my next gig. Contact me if you know of something interesting.

#

Dead simple task scheduling in Rails

Posted on 02/13/2009

So I was working on an Intridea project where I needed to send out a daily digest email.  The emails needed to be sent out on a scheduled interval, not as the result of some user action.  This meant that it would need to be handled outside of the normal request/response cycle.

Typically in the Rails world, when someone mentions long-running, or background tasks, you think either BackgrounDrb or Starling/Workling.  Those tools are fine and all -- actually, don't get me started on BackgrounDrb -- but I wanted something a bit more simple.

I didn't need queueing, or jobs, or anything like that.  I had only one task to manage.  I just want something that will say, "Once a day, do [task]", and that's all.

Also, I really didn't want to have to monkey with deployment tasks, be it with Vlad or Capistrano or whatever.  I wanted to just deploy as usual, and have it all just work, no extra processes to start or tasks to run.

This seemed like a tall order, but I began my search anyway.  Google led me to a number of pages about a number of tools, all of which included one or more of the things I was trying to avoid.  Of all places, I finally ended up on this page from the Ruby On Rails wiki.

Despite having only a one line mention near the bottom of the page, I decided to check out rufus-scheduler, and it turned out to be exactly what I was looking for.  There was no database table, queueing mechanism, or separate process to manage.  Just a simple scheduler to call out to your existing ruby code.

It couldn't get any simpler.  Here's how I set it up...

First, install the gem.

sudo gem install rufus-scheduler

I also froze it into vendor/gems by declaring the gem in the initializer block of environment.rb and then running rake gems:unpack.

Then I created a file called task_scheduler.rb in my config/initializers directory.   Inside this file is where the magic happens.  This is where it all goes down.  Are you ready?  Here it is...

scheduler = Rufus::Scheduler.start_new
    
    scheduler.every("1m") do
      DailyDigest.send_digest!
    end
    

Yeah, that's it. Seriously.

I was in disbelief myself until I started up the server and watched it send me an email.  In it's current state, it would send the digest every minute, which is not what I wanted.  Fortunately, the rufus-scheduler provides several ways to schedule your tasks.  Once I was ready, I changed it to more of a cron-style scheduler.

scheduler = Rufus::Scheduler.start_new
    
    # Send the digest every day at noon
    scheduler.cron("0 12 * * *") do
      DailyDigest.new.send_digest!
    end
    

You could also use scheduler.in or scheduler.at for one time tasks set to run at some point in the future.

I know a guy who's from "the future", but that's another story.

Anyway, there you have it.  Dead simple task scheduling in Rails.  It really doesn't get any easier than that.