Jens Krämer

Introducing Cronic - Cron like scheduling for Rails apps

 |  devops, ruby, cron, rails

This is kind of a sequel to my previous post about scheduling jobs with rufus-scheduler.

While the unicorn setup I described there runs nice and stable, following a similar approach with an application running on Passenger / mod_rails proved to be quite unstable due to Passenger’s more dynamic process handling. Whenever Passenger decides to kill one of your application processes due to low load or a given max requests per process limit, it may happen that decides to kill exactly that process where the scheduler is running. In this case you end up without scheduler until a new application process is spawned because of increased load. So a separate scheduling process was in order. Still very happy with the scheduling capabilities of the rufus-scheduler gem I started to build a daemon around it. Using Dante this turned out to be very easy.

A while later I decided to extract the tiny bits and pieces of code needed to glue Dante and Rufus together and integrate them into a Rails app into it’s own gem for easier re-use: Cronic.

Why build another job scheduler for Rails?

Yes I know there already are lots of job scheduling solutions out there, however none seemed to fit my needs:

While the last points can easily be implemented inside the jobs in question, i.e. using lock files, just like the Airbrake reporting it makes sense to have that built into the scheduler itself.

And to be honest - using Dante and Rufus Scheduler it was so dead easy to put this together, that most of the work went into boilerplate stuff like gemspec, docs and capistrano recipes.

Usage

I’ll just quote the readme here.

Add Cronic to your Gemfile and run Bundler

echo "gem 'cronic'" >> Gemfile
bundle install

Run the Rails generator and create job definitions

rails g cronic

This will set up script/cronic, which you will use to start / stop the daemon. It also creates the config/cronic.d directory where you will store your job definitions. Have a look at config/cronic.d/sample.rb to get an idea of how to define your jobs. For more information, be sure to visit the Rufus-Scheduler documentation. Every method that is available on a Rufus::Scheduler instance can be called in the job definition files located in config/cronic.d.

Run it

script/cronic -d -l log/cronic.log -P tmp/pids/cronic.pid

This will run cronic daemonized, logging to log/cronic.log, with a pid file located in tmp/pids. To run in the forground for testing purposes, just run the script without any parameters.

In order to stop the daemon, run

script/cronic -k -P tmp/pids/cronic.pid

And that’s it. Cronic comes with Capistrano recipes for automatic stop/start upon deployment, head over to the github repo for detailed setup instructions.

Comments

You can use Markdown here.

For the sake of spam checking any data you submit, including your IP address, will be transferred to the US based Akismet web service (akismet.com). If that's not acceptable for you, you can also reach me by other means.