Thursday, January 9, 2014

Scheduling java unit tests as cron jobs in Heroku

Most folks use Heroku for more than just one application. At any given time, you may have one production application running (with more than one dyno) while tinkering with other dev apps (only one dyno) that are nearing maturity and require regular upkeep for demos to customers.

Heroku will put any dev instances (only one dyno) to sleep after one hour of inactivity and when you start a demo, your first few requests may timeout and customers will be left with a poor impression of how your app performs.

So how do you keep your dev apps awake and available until you have enough market traction to scale them up?
  1. Since you can only have one process named web that gets HTTP requests routed to it, it is impossible to host two war files (prod-war and dev-war) side-by-side without merging them into one war with a common web.xml, spring configuration files, and non-conflicting URL endpoints. This is a lot of work.
  2. A neat workaround that I like to employ is using the Heroku Scheduler from my production instances to run functional unit tests against my dev instances to keep them alive.

  1. Anything that you can run as a one-off task in Heroku via: heroku run 'some command' ... can be run via this scheduler. Simply place 'some command' in the text input field under the task column and change the frequency to hourly.
  2. It may take some trial & error to figure out the right classpath for running your unit tests so I would advise utilizing heroku run 'some command' to figure out what it is that will work for you, before putting anything in the scheduler. Here's a sample:
    heroku run 'java -DunitTestNeedsSomeArg1=value_1 -DunitTestNeedsSomeArg2="complex value 2" -cp target/test-classes:target/myProjectName/WEB-INF/classes:"target/dependency/*":"target/myProjectName/WEB-INF/lib/*" org.junit.runner.JUnitCore com.my.test.TestRestRequest'
    • You may also realize that certain jars are available locally but missing from Heroku because you defined them as test-scoped in your maven project's pom.xml file ... you will need to remove the scope limitation in order to get the unit tests working on the Heroku side.
    • Once you have something working, then just cut/paste the content inside the single-quotes as the scheduled task to run hourly.
  3. When looking through the logs, any lines spit out by the hourly one-off task will be prefixed like so:

0 comments:

Post a Comment