Heroku provides a free add on for running scheduled jobs. This provides a convenient way to run scheduled tasks in an on-demand dyno, freeing your web dynos to focus on user requests. I’m currently writing a node.js application in coffeescript that has some modest job scheduling needs.
Heroku’s documentation is a little thin on explaining this particular use case, however a good starting point is reading the One-Off Dyno Documentation. The important concept to remember is that if you can run your command using “heroku run xxx”, you’ll be able to run it in the scheduler. These one-off dynos should be place in a bin/ directory in your project root.
My first attempt is below. Note that we set it to use our node install to run (Heroku installs node at /app/bin/node).
#! /app/bin/node
require('../server/jobs/revenueCalculator').runOnce()
Deploy to heroku and run the following command using the toolbelt. We get an error immediately.
heroku run runJob
Error: Cannot find module '../server/jobs/revenueCalculator'
Next I wanted to try running interactively, using the coffeescript interpreter:
heroku run coffee
Running `coffee` attached to terminal... up, run.6960
coffee> x = require('./server/jobs/revenueCalculator')
{ start: [Function], runOnce: [Function] }
coffee> x.runOnce()
Job Started
Job Complete
Now we seem to have zeroed in on the problem. Perhaps the script will work if we run it using coffeescript, rather than the node executable. Edit bin/nightlyJob as follows:
#! /app/node_modules/.bin/coffee
job = require '../server/jobs/revenueCalculator'
job.runOnce()
Deploy to heroku and run.
heroku run nightlyJob
Running `nightlyJob` attached to terminal... up, run.9139
Job Started
Job Complete
Using #! /app/node_modules/.bin/coffee in a standalone script to call the application code seems to do the trick. Now, lets add the heroku scheduler to our app, and configure the job to run nightly.
heroku addons:add scheduler:standard
heroku addons:open scheduler
A browser should pop open, and we can schedule our nightly job.
Thats all folks.