I’m working on the chapter on Messaging and Scheduling for San Gria (Chapter 14), and I’ve finally had a chance to explore some parts of the sensational Grails Quartz plugin that have been on my to-do list for ages. I’ve had a good explore of non-re-entrant jobs, passing state between jobs, programmatically dealing with jobs, and now I’m having a look at the db-persistent jobs.
One thing that I’ve wanted to explore for the longest time is the ability to pause and resume jobs programmatically via a UI. For example, before I converted groovyblogs.org to a messaging architecture, I was really keen to add an admin UI to pause and resume polling of jobs (for instance when I was doing deploying a new version of the browser snapshot service). Now I know how :-)
First off, if you’re going to be doing programmatic stuff with your jobs, you need to put them in a group (yes you can use a default group, but it makes things easier to follow). Here’s our sample:
class ControllableJob { def timeout = 5000 // execute job once in 5 seconds def concurrent = false **def group = "myServices"** def execute() { println "Controllable Job running..." } }
Ok, With our job named, we can do all sort of pausing and resuming operations. Let’s whip together a quick UI to post our list of operations in a “operations” field:
To take advantage of the quartz scheduler operations, you need to do a “def quartzScheduler” to get the injection happening. After that, you have a wealth of Scheduler interface methods to work with. Here’s our controller method:
def show = { def status = "" switch(params.operation) { case 'pause': quartzScheduler.pauseJob("ControllableJob", "myServices") status = "Paused Single Job" break case 'resume': quartzScheduler.resumeJob("ControllableJob", "myServices") status = "Resumed Single Job" break case 'pauseGroup': quartzScheduler.pauseJobGroup("myServices") status = "Paused Job Group" break case 'resumeGroup': quartzScheduler.resumeJobGroup("myServices") status = "Resumed Job Group" break case 'pauseAll': quartzScheduler.pauseAll() status = "Paused All Jobs" break case 'resumeAll': quartzScheduler.resumeAll() status = "Resumed All Jobs" break } return [ status: status ] }
Notice that the pause() and resume() for individual jobs take the full name of the job (“ControllableJob”) as the argument. Notice also that the Groovy switch statement is insanely useful - you can even mix string and integers in the case statement if your switch var is dynamically typed - awesome! (more info).
Anyways… must get back to exploring the database persistent options for quartz jobs so I survive a restart if need be! The end of Chapter 14 is in sight, and those people who have pre-purchased the book via the Manning MEAP program should get it towards the end of the next week/early following week. And we’ll have another 4 chapters going out in time for Christmas!
Happy programmatic scheduling! (Oh, and the sample app above is on github)