Dead simple task scheduling in Rails

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.

rails task-scheduling

 

Leave a Comment


 Name is required
 Email is required