Ben Nadel
On User Experience (UX) Design, JavaScript, ColdFusion, Node.js, Life, and Love.
I am the chief technical officer at InVision App, Inc - a prototyping and collaboration platform for designers, built by designers. I also rock out in JavaScript and ColdFusion 24x7.
Meanwhile on Twitter
Loading latest tweet...
Ben Nadel at the NYC Tech Talk Meetup (Aug. 2010) with:

Creating A Centralized Point Of Entry For ColdFusion Scheduled Tasks

By Ben Nadel on
Tags: ColdFusion

I have never been a huge fan of ColdFusion's scheduled tasks. That's just an odd fear based on the fact that I have to rely on something outside of my applications. But, the fact is, scheduled tasks are essential if you want to do anything on a scheduled basis that is NOT triggered by user actions. I am also not a huge fan of creating / modifying / deleting scheduled tasks using the ColdFusion CFSchedule tag as it tends to leave phantom tasks running until the ColdFusion service gets restarted.

In order to deal with all of that emotionally, what I have started doing is creating a single point of entry for scheduled tasks in my ColdFusion applications. I have a single ColdFusion template that launches all of my application's scheduled tasks:

  • <!--- Kill extra output. --->
  • <cfsilent>
  •  
  • <!---
  • Send girlfriend random text message so that
  • she knows that I am thinking about her.
  • --->
  • <cfhttp
  • url="./tasks/send_random_text_message.cfm"
  • method="GET"
  • timeout="1"
  • throwonerror="false"
  • />
  •  
  • <!--- Clean up temp files. --->
  • <cfhttp
  • url="./tasks/purge_temp_files.cfm"
  • method="GET"
  • timeout="1"
  • throwonerror="false"
  • />
  •  
  • <!--- Send out scheduled emails. --->
  • <cfhttp
  • url="./tasks/scheduled_emails.cfm"
  • method="GET"
  • timeout="1"
  • throwonerror="false"
  • />
  •  
  • </cfsilent>
  •  
  • <!--- We are done running tasks. --->
  • Done.

As you can see, this single point of entry turns around and launches additional scheduled tasks using CFHttp calls. Each CFHttp call is given one second to execute before it times out (without error) and the current page moves onto the next task.

The down side to this is that each task has to know a bit more information. Tasks cannot assume they are only run once every N hours or days. Since this one point of entry is responsible for every scheduled task on the site, it must run as often as the smallest required time interval. This means that a task designed to run once a day might end up getting called once every 15 minutes. That task has to know to ONLY run once per day even though it is "asked" to run much more often.

The up side to this, however, is that you only need to set up one scheduled task in the ColdFusion administrator (per application). If you have any additional scheduled task requirements all you have to do is update your point of entry. You never need to go back to the ColdFusion administrator for task set up for the application (unless, of course, you need to increase / decrease the interval at which the task runs).

So far, I have used this with great success. And, I find that it forces me to write much better, smarter scheduled tasks that don't rely on the scheduled task interval.




Reader Comments

I like this idea, and I think the cons that you brought up could be remedied with some magic...I am going to investigate more into this design because you and I share the same fears.

Reply to this Comment

Derek,

I agree. For instance, one of the sample tasks was an automated email sender. If you were grabbing emails out of a database, you could certainly have a field for date_last_sent which could be updated / read for task execution.

Let me know what kinds of stuff you come up with.

Reply to this Comment

Sami,

That looks pretty cool. I have not seen that before. I like that the CFC handles the "interval" hand-holding. Very cool.

Reply to this Comment

The other downside is that if you don't put try-catch in each item if one fails they all fail. Also if you put a bug in your script, none run.

Reply to this Comment

Chris,

The CFTry / CFCatch is not necessary since the failure will happen in the page being called via CFHttp, not the primary task page. If the page getting called fails, the only thing the calling page knows is that the error message gets returned in the CFHTTP.FileContent attribute; it sees it as just some text... not an error.

But yes, if there is an error in primary page, some or all will fail to run. But of course, that is what testing is for :)

Reply to this Comment

Ben,

neat idea. I also like the idea of sending your girlfriend text messages (even if it's a fictional idea, he he). On that note, you should replace the "girlfriend" with a variable so it could be used for a "wife" also, lol. Keep up the good work.

Reply to this Comment

Definitely a tried and true strategy for scheduling.

Especially for related/dependent tasks.
- Error handling between steps
- Success required/optional
- Retry 10 times, then quit
- Do if not done already today, this hour
- Pick up where left off, before error
- Avoid multiple exec if still running

It's simple enough to set up separate sched tasks for different purposes.
- Hourly custom session mgmt cleaning
- Daily batch imports/exports
- Persistent loop/daemon (restarted if not running)

The imagination abounds.

Reply to this Comment

@Alex,

I never even thought of doing the "Try 10 times and then quit" aspect. Nice suggestion!

Reply to this Comment

Hi Ben,

I keep getting a duplication on processing when this event happen in my server.log...any of you guys have any idea about this. I know that neo-cron is where you put the scheduled task parameter on it but why is it modified without my intervention.

This is what i got in the server.log :-

neo-cron.xml has been modified . Reloading the service coldfusion.scheduling.CronServiceImpl@13de08a

URGENT ASSISTANT required on this matter.

Thanks....

Reply to this Comment

@Wan,

I used to get duplicate tasks being run when I messed around with CFSchedule. How are you creating the scheduled tasks?

Reply to this Comment

@Ben,

Everything is ok until this thing come out from no where and it is started to duplicate by itself.

I pumped in a lot of data into the scheduled task for every 15 seconds interval. Do you think this is the caused of it. Or there is any other reason why it became like this.

Reply to this Comment

@Wan,

I am surprised that you can get a scheduled task to run every 15 seconds. I believe that the last time I tried it, it had to be done ever 60 seconds minimum. Are you running several scheduled tasks?

Reply to this Comment

@Ben,

I think that will not a big suprised since you can set it at CFSCHEDULE but the problem is only on processing burden to the server.

Yeap...there is several scheduled tasks running at the same time.

Ben, I got another question for you...Let say if I got two machines with the same serial number, will it gives any impact to my scheduled task. Because keep getting the remark in the server log 'Same Serial Number found on another CF server - server may be out of compliance'. Is it considered clustered? I read somewhere in the internet that if i have clustered the coldfusion...I might got a problem on the neo-cron.xml which causing the duplication.

Reply to this Comment

@Wan,

Once you go past one server, you get out of my area of understanding. I know very little about clustering. Sorry.

Reply to this Comment

@Ben,

Any reason you know of that AJAX would not work from a scheduled tasks? Since JS is client side and the scheduled task is being called from the server side, do you think there is a bit of an issue?

There is the RESOLVE URL attribute of the scheduled task.

What are your thoughts?

Reply to this Comment

@Jeff

Ajax would not work.

HTTP responses, including JavaScript are not browsed by the task scheduler.

Scheduled tasks are a way of running CF as generic scripts. Not HTTP requests/responses.

No?

Reply to this Comment

@Anyone

RE: scheduled task and ajax (read previous two post) ... not working ... yes, makes total sense.

Would CFTHREAD be a solution? There are many tasks being fired off with AJAX and no response back to the parent call. The AJAX was being used to just fire off the tasks independently. What about CFTHREADING the task since none of the data is dependent upon the other?

Note: This tasks is usually run when the server has very low traffic. Also, if you loaded up the server with 20 CFTHREAD calls, would it operate similar to AJAX in that it would initially load up the available threads and then the remaining would stack up until threads were available?

Reply to this Comment

@Jeff,

Yes, CFThread would work, and in fact, I have created scheduled task sub-processes in this way. You have the single point of entry, and then each subsequent task is launched using a CFThread. You just have to be careful about passing data into it.

Reply to this Comment

Hi ben, I have created as Scheduled task in my admin Programatically, But it shows "Connecction Failue: Status Code Unavaliablle" Error!

i am trying something like this

<cfif isScheduledTaskExists("taskname")>
<cfscedule action="run" name="taskname">
<cfelse>
<cfschedule action="update" httprequest="yes" url="/common/files/coldfusion/action.cfm" resolveurl="yes"> <!--- Other attributes being added to it --->
</cfif>

Can You guide a bit on this

Reply to this Comment

For this one particular app, I have set up my scheduled tasks in CFAdministrator a little differently, setting up one for each interval I need (2 minutes, 15 minutes, 4 hours, one day) and each task calls it's own function in an Automation.cfc controller. I can then drop cfhttp calls into whatever interval function I need, and I'm only returning to cfadmin if I need a different interval (or different run windows, etc.) configured.

I also created an init() function in my Automation controller that uses CFSCHEDULE tag to "update" (create) the intervals in the cfadmin on application start... so I'm rarely going to cfadmin at all... so this one file pretty much spells out exactly what the automation config is for the app, from creating the intervals to outlining exactly what happens at each interval.

My question is regarding your decision to set each cfhttp call to a one-second timeout. According to the (CF8) docs:

"timeout" : Value, in seconds, that is the maximum time the request can take. If the time-out passes without a response, ColdFusion considers the request to have failed.

I have a few interval functions that need to do several CFHTTP calls in a row. If I set the timeout to 1 second and the throwonerror to false, can I assume that the actual call still RUNS, I've essentially just told the app not to wait around for it, and move on to the next CFHTTP call? This doesn't have an adverse effect on the actual page being called... the server still completely processes that request separately?

I think I know the answer, but thought it would be helpful to have that clarified here....

Thanks as always... seems whenever I'm Googling for information like this, your name always comes up. ;)

Reply to this Comment

Post A Comment

?
You — Get Out Of My Dreams, Get Into My Comments
Live in the Now
Oops!
Comment Etiquette: Please do not post spam. Please keep the comments on-topic. Please do not post unrelated questions or large chunks of code. And, above all, please be nice to each other - we're trying to have a good conversation here.