Yesterday I blogged about my migration of ColdFusion Bloggers from ColdFusion to Node. During that conversion, I was impressed by how easy it was to set up a scheduled task. (Once I got past the vagaries of the CRON syntax.) I remembered that ColdFusion 10 had added some dramatic improvements to scheduled tasks. You can read a high level review of that here: Using Scheduler. While I knew about these improvements, I never actually got around to playing with them. Last night I did - and here's what I found.

I decided that I would play with two features that were new to scheduled tasks in ColdFusion 10:

  • Application-specific tasks
  • CFC based tasks (instead of URLs)

I built the following Application.cfc as a demo:


component {

	this.name = "scheduletests.one";
	
	public boolean function onApplicationStart() {
		//register my tasks
		cfschedule(action="update", task="FirstTask", mode="application",
		interval="daily", eventHandler="tests.scheduletests.one.taskrunner",
		startDate="1/1/1900", starttime="13:00" );
		return true; 
	}	

	public boolean function onRequestStart() {
		if(structKeyExists(url, "reinit")) {
			applicationStop();
			location(url="./");	
		}	
		return true;
	}

}

I used onApplicationStart as my event registration place. Technically it doesn't need to be there, but that made the most sense. I just had to add a quick url "hack" in onRequestStart to give me a quick way to rerun it properly.

Setting the task as application specific was as simple as mode="application". When you do this, the task still shows up in the ColdFusion Administrator, but if another application uses the LIST feature of cfschedule, it won't see your task. And obviously - two different applications can have the same task name. Here is a screen shot showing how the CF Admin differentiates between the different types of tasks.

shot1

That part was rather simple, but then I found myself fighting the somewhat poorly documented rules for creating tasks. So I wanted a daily task. I forgot, though, that ColdFusion requires a start date for such a task. In my mind it should just start tomorrow if not specified. What's weird is that if you leave off startdate, you don't get an error. Instead, the task was registered as a chained task. I highly recommend keeping the CF Admin open as you test creating scheduled tasks from code. If it looks funky in the Admin then you've done something wrong.

I then tried using a CFC for my scheduled task. At the time I played with it, the docs were very unclear about how to use it. They simply said that the CFC must implement ITaskEventHandler. I did some digging and discovered that this is actually in the CFIDE/scheduler folder. I edited the official docs wiki to include the full path. Here is a bare bones CFC that uses the interface:

component implements="CFIDE.scheduler.ITaskEventHandler"  {
	
	public boolean function onTaskStart(Struct context) {
	};
	
    	public void function onTaskEnd(Struct context) {
    	};

	public void function onMisfire(Struct context) {
		
	};
	
	public void function onError(Struct context) {
	};

	public void function execute(Struct context) {
		writelog("executed #serializejson(context)#");
	};
	
}

That argument, context, is not documented for the execute method, but is documented for the others. It contains the group (another new feature in ColdFusion 10), the task name, and the mode. As you can guess, this means you could do some code sharing between similar tasks. So you could have tasks like so: petCat, petDog, petDragon, etc, all using the same CFC and simply inspect the name value to determine what to do. That's similar I suppose to using one CFM for N tasks and passing different URL arguments.

All in all - outside of the weirdness of arguments for defining tasks - I really like this improvement. Anyone using them?