Programmatically Deleting Scheduled Tasks In ColdFusion

Posted October 18, 2006 at 3:34 PM by Ben Nadel

Tags: ColdFusion

Inspired by Mike Schierberl's use of Java to programmatically delete ColdFusion scheduled tasks, I decided to try and to accomplish the same thing with plain old ColdFusion. I have tried to do this in the past, but always failed (and ended up creating a phantom task on the server - yikes!). I would have never been able to do this without Mike's absolutely critical explanation:

The Adobe techNote is somewhat misleading, it turns out that delete does work through the cfschedule tag, but the problem arises when the scheduled task tries to delete itself.

That is a really, really important note indeed. But, I would like to take that one step further: A scheduled task cannot be deleted while it is still running. Well, at least not programmatically I think.

So, the trick here, is to be able to get a scheduled task to call another page that then deletes the scheduled task, AND this has to be done only after the scheduled task has stopped running. Sounds complicated? It's actually very simple to do and it all comes down to page timeouts.

Let's take a quick look at the code. Here is the page getting called by the scheduled task:

  • <!--- Make sure the page can only run for 5 seconds. --->
  • <cfsetting
  • requesttimeout="5"
  • />
  •  
  •  
  • <!--- Get this directory. --->
  • <cfset strDirectoryUrl = GetDirectoryFromPath(
  • "http://#CGI.server_name##CGI.script_name#"
  • ) />
  •  
  • <!---
  • Call execute task page. This is the page that will delete
  • the currently running task. Put in a CFTry / CFCatch blocks
  • because you never know how CFHttp might mess up.
  •  
  • Tell the CFHttp tag to only allow ONE second of timeout
  • time before it gives up waiting and continues on with the
  • page processing.
  • --->
  • <cftry>
  •  
  • <cfhttp
  • url="#strDirectoryUrl#execute_task.cfm"
  • method="GET"
  • useragent="Mozilla/5.0"
  • timeout="1"
  • />
  •  
  • <cfcatch>
  • <!--- An error occurred. --->
  • </cfcatch>
  • </cftry>
  •  
  •  
  • <!---
  • Trace the execution to a file just so we can make sure we
  • know exactly when the task is running.
  • --->
  • <cffile
  • action="APPEND"
  • file="#ExpandPath( './trace.txt' )#"
  • output="BT2 - Executed: #TimeFormat( Now(), 'hh:mm:ss:l' )#
  • addnewline="true"
  • />

Now, let's take a look at the execute task page that deletes the scheduled task:

  • <!---
  • Get the currently executing thread and force it
  • to sleep for 10 seconds.
  • --->
  • <cfset CreateObject(
  • "java",
  • "java.lang.Thread"
  • ).CurrentThread().Sleep(
  • JavaCast( "long", 10000 )
  • ) />
  •  
  •  
  • <!--- Kill task. --->
  • <cfschedule
  • action="DELETE"
  • task="BenTestTask2"
  • />

This all works quite nicely. And, as I said before, it's all thanks to page timeouts.

Take a look at the execute task page. Notice that the first thing the page does is sleep (thanks Mark Mandel's code example for asyncHttp) for 10 seconds. Then, after sleeping, it deletes the task. Now, look at the original task page. Notice that it only allows 5 seconds for page execution and the MINIMAL amount of timeout for the CFHttp request (one second) to wait for a response. This means that the calling page (the original scheduled task) should either finish executing OR timeout in some way before the Sleep() on the target page ever finishes. The bottom line: we can be sure that by the time the CFSchedule tag is executing, the original page has is NO LONGER RUNNING.




Reader Comments

Oct 18, 2006 at 4:17 PM // reply »
1 Comments

Nice work Ben, nice to finally understand what the root of the problem was. Hopefully this will be fixed in Scorpio (although I don't have my hopes up considering they knew about the issue in CF6)

Couple of things I would add...

1) may want to consider adding throwonerror=no to the cfhttp tag. You won't see the error because it is in a scheduled task, but I think it would throw an exception every time

2) may want to think about implementing a lock to make sure that the scheduled task isn't running. Think of a scenario with a scheduled task running every 60 seconds. If your first request takes 58 seconds to process, it may start a new thread 2 seconds later. At this point the delete task is waiting 10 seconds, and when it tries to delete, the task will be running again. Unlikely, but it may cause some strange behavior.

Nice work!


Oct 19, 2006 at 7:21 AM // reply »
11,238 Comments

Mike,

For starters, never could have done without your dynamite insights first. As for the throwonerror, I think it defaults to not throwing an error, however, it would be nice to see it explicitly written out.

As for the lock... I follow, that, would be cool. I figure I could put a NAMED lock on the entire scheduled task, then put a lock on th execute_taks.cfm page as well.... hmmm, but then one could lock the other and vice versa. I will play around.


jM
Nov 4, 2006 at 2:22 PM // reply »
9 Comments

Ben,

Very helpful post. Bit thanks to both you and Mike. Did you ever have time to investigate locking ideas?


Nov 5, 2006 at 10:56 AM // reply »
11,238 Comments

I have not looked into the locking issue yet, but I have an idea for something even better. Hopefully I can post soon.


jM
Nov 8, 2006 at 12:47 AM // reply »
9 Comments

I'll stay tuned.. I look forward to reading about your new idea.


Nov 8, 2006 at 7:25 AM // reply »
11,238 Comments

JM,

My new idea didn't work. I thought maybe I could do a page transfer (GetPageContext().Transfer()) to the page that would be deleting the task, but it did not work. The Transfer() method should kill the current page request, but I guess from ColdFusion's standpoint it's still the same thread or something. I don't know enough about what is going on underneath to understand why any of it doesn't work.

Sorry.


jM
Nov 9, 2006 at 6:06 PM // reply »
9 Comments

Ben,

This may be a dumb question but what is getPageContext().Transfer()? I only know about getPageContext().forward() and include(). Is transfer() like ASP's Server.Transfer()?


jM
Nov 9, 2006 at 6:09 PM // reply »
9 Comments

Ben,

I forgot to say thanks for the followup. I appreciate it.


Nov 10, 2006 at 7:21 AM // reply »
11,238 Comments

JM,

Sorry, that was my mistake. I did mean GetPageContext().Forward(). I don't know what Transfer is... i think I had something else on my mind at the time.


jM
Nov 13, 2006 at 5:08 AM // reply »
9 Comments

Ben,

No problem. You know I was reading Mike's blog entry and got to wondering about his comment: what happens if the scheduled task continues processing after the asynch http call.

I ran a few tests using CurrentThread().sleep() to force the scheduled task to continue executing for 30 seconds after the http call. The results I observed were that it created a phantom task.

Not that surprising I guess but it got me thinking about adobe's tech note 18361. Can you really delete a task through the CF Administrator if the task is still executing? So I created a recurring task that ran every 2 minutes. Then tried deleting the task in the ColdFusion Administrator (while the task was executing). The results were the same. It created a phantom task.

I'm curious if anyone else sees the same results or flaws in the test logic.


Nov 13, 2006 at 7:15 AM // reply »
11,238 Comments

jM,

That's very interesting. I guess a task cannot be deleted through any method so long as the task is still running. Doesn't that seem strange? You would think that the thread running it would be totally separate from the definition of it... why should the two overlap?


jM
Nov 16, 2006 at 12:27 AM // reply »
9 Comments

Ben,

I ran some more tests. Stranger still is that "updates" seem to have no effect either, if you apply the changes while the task is running. I'm wondering if the thread executing the task is blocking changes or maybe the updating thread isn't communicating the changes to the running task. Without knowing about the internal workings this is all just guesswork of course. But if my tests are correct then you cannot even modify a task through the CF Admin, if the task is currently running. Thats a bit disturbing..


Nov 16, 2006 at 7:17 AM // reply »
11,238 Comments

jM,

Nice testing! Yeah hopefully this is something that they can fix in the upcoming versions. It has been known about (to a degree) for some time now.


jM
Nov 16, 2006 at 9:00 PM // reply »
9 Comments

Ben,

Yes its definitely been around for a while. I am bit surprised that I haven't read more about the issue as it relates to any attempts to change a running task. The technote only mentions a problem with deletes. The neocron.xml file problem seems to have been fixed but the rogue task behavior still persists.

Like you said, hopefully it will get fixed in newer versions. It would also be nice to see some extended task information like "last run on date" or the "next scheduled date"... and of course a "kill" task feature might be nice ;)


Jun 11, 2007 at 8:04 PM // reply »
1 Comments

This blog has been very informative for me.

Carmelo Lisciotto


Nov 6, 2007 at 7:54 PM // reply »
34 Comments

You can also write a coldfusion template to edit the neo-cron.xml file and delete the scheduled tasks. This example:

http://www.coldfusionguy.com/ColdFusion/blog/index.cfm/2007/10/28/ColdFusion-Script-to-clean-expired-or-disabled-scheduled-tasks

Demonstrates how to delete expired and disabled scheduled tasks but you could modify it to add/edit/delete the scheduled tasks based on other factors as well.


Nov 7, 2007 at 8:58 AM // reply »
11,238 Comments

@Scott,

That is a cool idea. The only thing worries me about it is that the path the XML file is hard coded. Other than that, very cool.


Nov 7, 2007 at 5:09 PM // reply »
34 Comments

@Ben

that's a good point. I wouldn't normally hard code something like that either, but it was just a simple proof of concept for a blog entry, so I try to keep them as straightforward as possible. If I were really in the need for something like that, I would probably make a custom tag, or more likely these days a CFC, that could add, edit, and delete the scheduled tasks and I would use the #server.coldfusion.rootdir# to get the coldfusion root folder in my cffile tags. And now that I'm thinking about it I would put named cflocks around the process to protect the integrity of the file. Perhaps I should add a little note about that on my entry for people that don't yet know the potential risks with editing these kinds of files.


Nov 7, 2007 at 5:13 PM // reply »
11,238 Comments

@Scott,

Yeah, that sounds like a good solution. I forgot about the SERVER-scoped settings. I need to take another look at those to see what googies can be leveraged.


Nov 7, 2007 at 6:02 PM // reply »
34 Comments

There's not too much that's usefull, rootdir is about the only one I ever really use. here's all of the server variables as of CF8:

server.COLDFUSION.APPSERVER
server.COLDFUSION.EXPIRATION
server.COLDFUSION.INSTALLKIT
server.COLDFUSION.PRODUCTLEVEL
server.COLDFUSION.PRODUCTNAME
server.COLDFUSION.PRODUCTVERSION
server.COLDFUSION.ROOTDIR
server.COLDFUSION.SUPPORTEDLOCALES
server.OS.ADDITIONALINFORMATION
server.OS.ARCH
server.OS.BUILDNUMBER
server.OS.NAME
server.OS.VERSION



Post A Comment

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.

Please review the following issues:

Author Name:


Author Email:

Author Website:

Comment:

Supported HTML tags for formatting: <strong>bold</strong>   <em>italic</em>   <code>code</code>







  • Help Wanted - Find Your Next ColdFusion Job
Ben Nadel's Company - Epicenter Consulting Recent Blog Comments
May 17, 2013 at 7:42 PM
HashKeyCopier - An AngularJS Utility Class For Merging Cached And Live Data
Ben - thanks so much for posting these Angular articles and findings, they've been a huge help towards learning one of the more 'complex' JavaScript frameworks out there (IMO). I have been using Angu ... read »
May 16, 2013 at 5:01 PM
UPDATE: Parsing CSV Data Files In ColdFusion With csvToArray()
Your code was the closest thing I've found to obtaining some direction for converting ISO fields to values that CF can translate properly. Thank you for posting! ... read »
May 15, 2013 at 10:37 PM
Very Simple Pusher And ColdFusion Powered Chat
hi id making plz easy ... read »
May 15, 2013 at 6:07 PM
Making SOAP Web Service Requests With ColdFusion And CFHTTP
Ben, you once again saved my bacon at work. Thank you, thank you, thank you! ... read »
May 15, 2013 at 4:15 PM
What If All User Interface (UI) Data Came In Reports?
@Josh, Thanks! @Ben, I definitely recommend the David West book "Object Thinking" I've been quoting from. It goes deeply into the philosophy and history of OO programming. His breadth ... read »
May 15, 2013 at 11:36 AM
Ask Ben: Print Part Of A Web Page With jQuery
I found this helpfull when you need to keep (refresh) the original parent page after closing the iframe child print dialog (Hoping you're not using a form at this time so it won't submit again): On ... read »
May 14, 2013 at 7:13 PM
What If All User Interface (UI) Data Came In Reports?
@Jonah, If there's any books you'd recommend on the subject of domain modelling, I'd love to hear it. I just downloaded the free PDF of "Domain Driven Design Quickly". Figured I'd give it ... read »
May 14, 2013 at 6:57 PM
The UX Of Prototyping: Low-Fidelity Is The New High-Fidelity
@Phillip, I'm not sure I follow what you mean? Are you saying that you looked at the list of widgets provided by the jQuery UI and let that be your style guide? ... read »
InVision App - Prototyping Made Beautiful With Prototyping Tools