1 min read

A Free Cron for Heroku via Platform API and Openshift

Heroku has a free cron add-on, but you require a credit card, Openshift has a cron gear but unfortunatly other problems. Heroku launched recently the Platform API, so let's hack a cronjob!

It's important to detach the long tasks from HTTP requests. Data Backup, feed fetching,.. are good examples of task, inside an Heroku project you can do:

heroku run rake fetch_feeds

And "rake fetch_feeds" will be executed remotely in your instance, but how is possible to automate the same request?
Easy! From another web cron and the heroku api!

APP_KEY=`(echo -n ":" ; heroku auth:token) | base64` ; echo $APP_KEY                                       ⬆ ◼
KmQwZjAyMz Your Secret key kxMzc5NzIzZjY4Cn==

Now you need an app on Openshift, you can use this minimal Sinatra app or the default one.

rhc create-app crontest -t ruby-1.9 && cd crontest
rhc cartridge-add cron

The cron scripts are managed by the files inside .openshift, lets add .openshift/cron/minutely/crony and make it executable.

#!/bin/env ruby

# This is Magic Cron
def every ( minutes, name='cronjob' )
  lock =  "#{ENV['OPENSHIFT_DATA_DIR'] || ''}.#{name}.lock"
  if  !File.exists?(lock) or (Time.now - File.ctime(lock) > minutes)
    File.write(lock, "")
    true
    yield
  else
    false
  end
end
class Fixnum; def mins; self * 60; end; end

### Your script here ###

every 1.mins do
  puts 'ciao'
end

every 2.mins, 'anotherjob' do
  puts 'another'
end

paste

git add . && git commit -m "+ cron" && git push

Connecting to Openshift via ssh we should see the lock files in $OPENSHIFT_DATA_DIR.

Finally we can add the Heroku Platform API part:

every 15.mins, 'fetch_feeds' do
  `curl -n -X POST https://api.heroku.com/apps/MYHEROKUAPP/dynos  -H "Accept: application/vnd.heroku+json; version=3"  -H "Content-Type: application/json" -H "Authorization: KmQwZjAyMz Your Secret key kxMzc5NzIzZjY4Cn==" -d "{\"attach\":false,\"command\":\"rake fetch_feeds\"}"`
end