CFSetting RequestTimeout Updates Timeouts, It Does Not Set Them

Posted April 4, 2007 at 3:42 PM

Tags: ColdFusion

That title probably doesn't make a lot of sense. What I mean by that is that when you use a CFSetting tag and set the RequestTimeOut attribute, the value you assign does not just apply to everything going forward - it applies to everything going forward in the context of everything that has already happened. Ok, maybe that doesn't clear anything up. What I mean to say is that the RequestTimeOut attribute does not determine the amount of time left, it determines the amount of processing time allowed in total.

Here is a demo to help explain what I am saying. For this example, I use a ColdFusion user defined function named KillTime(). This function simply runs a loop until a given amount of time has passed:

 Launch code in new window » Download code as text file »

  • <cffunction
  • name="KillTime"
  • access="public"
  • returntype="void"
  • output="false"
  • hint="I kill time for the given miliseconds.">
  •  
  • <!--- Define arguments. --->
  • <cfargument name="MS" type="numeric" required="true" />
  •  
  • <!--- Get start and end tick out values. --->
  • <cfset var intStart = GetTickCount() />
  • <cfset var intEnd = (intStart + ARGUMENTS.MS ) />
  •  
  • <!--- Loop until this time is killed. --->
  • <cfloop condition="(GetTickCount() LT intEnd)">
  •  
  • <!--- Just try to kill some processing time. --->
  • <cfset intStart = (intStart * Pi()) />
  •  
  • </cfloop>
  •  
  • <!--- Return out. --->
  • <cfreturn />
  • </cffunction>

Now, with that function in mind, here is the test code:

 Launch code in new window » Download code as text file »

  • <!--- Set the current time out to be 3 seconds. --->
  • <cfsetting requesttimeout="3" />
  •  
  • <!---
  • Get the millisecond start time for page processing
  • (so that later on, we can check to see how long
  • the page ran overall).
  • --->
  • <cfset intStart = GetTickCount() />
  •  
  •  
  • <!--- Try to kill some time. --->
  • <cftry>
  •  
  • <!---
  • Here, we are killing time - 4 seconds to be
  • approximate. This will exceed the request time
  • out set above (3 seconds) and will throw an error.
  • --->
  • <cfset KillTime( 4000 ) />
  •  
  •  
  • <!--- The KillTime() method call has timed out. --->
  • <cfcatch>
  •  
  • First Timeout!<br />
  •  
  • <!---
  • In an attempt to "recover" from this time out,
  • update the request time out to be six seconds.
  • --->
  • <cfsetting requesttimeout="6" />
  •  
  •  
  • <!--- Try to kill some more time. --->
  • <cftry>
  •  
  • <!---
  • We are going to try and kill about four
  • seconds. If this is in terms of the six-second
  • timeout set above, this should NOT timeout.
  • However, if this is in the context of the
  • overall page time (including previous kill time
  • calls), then this will timeout.
  • --->
  • <cfset KillTime( 4000 ) />
  •  
  •  
  • <!--- The KillTime() method has timed out. --->
  • <cfcatch>
  •  
  • Second Timeout!<br />
  •  
  • </cfcatch>
  • </cftry>
  •  
  • </cfcatch>
  •  
  • </cftry>
  •  
  •  
  • Total Time: #(GetTickCount() - intStart)#

That gives us the following output:

First Timeout!
Second Timeout!
Total Time: 6016

Now, if you look at the code, and the output, you will see that both calls to KillTime() threw timeout exceptions. The first one is straight forward - we tried to kill 4 seconds when the current request timeout only allowed 3 seconds. But, then we set the request timeout to be 6 seconds. In this second KillTime() request, we try to kill 4 seconds. If the previous 6 second timeout was a NEW timer, then this would not timeout (4 is less than 6). However, this second KillTime() method times out. This shows us that request timeout settings don't "add" time, they merely update how much total time is allowed.

Aside from the fact that this gives us a little more insight into using multiple CFSetting tags (which might not be totally obvious - it wasn't to me), it also proves that when a tag or block of code throws a request timeout exception, ColdFusion doesn't die right away - there is some wiggle room in which to recover or potentially add more execution time.

Download Code Snippet ZIP File

Post Comment  |  Ask Ben  |  Permalink  |  Other Searches  |  Print Page




Learning ColdFusion 9 - ColdFusion 9 tutorials, samples, examples, demos

Reader Comments

Apr 4, 2007 at 4:51 PM // reply »
19 Comments

This would make sense, Ben, as ColdFusion uses output buffering by default, and you must explicitly tell it to flush the contents of the buffer. This is unlike language like PHP, for example, which flush content out as it is processed, and you must explicitly tell it to buffer output if you wish for that behavior.


Apr 4, 2007 at 4:55 PM // reply »
6,516 Comments

@Adam,

While I agree with you on the buffering feature, I am not sure how buffering relates the page timeout?


Apr 4, 2007 at 5:52 PM // reply »
26 Comments

good to know, Ben. Thanks!


Apr 4, 2007 at 8:21 PM // reply »
19 Comments

I cannot say with any authority, however I have spent a little time writing my own language interpreters, and found that when assembling my page into my output buffer anytime I found a command that would modify program execution settings, I would put those into my script's environment settings, and overwrite any existing value.

That is essentially what I figure ColdFusion is doing. This is a setting that affects this request's processing environment, and it isn't "queuing" them up, but simply storing the last value.

Once again, no authority, just assumtions based off behavior and my own code in the past. *shrug*


Apr 4, 2007 at 10:22 PM // reply »
97 Comments

What happens if you remove the second requesttimeout setting? Since you've already caught the exception and handled it, how much more wiggle room does CF allow you?


Apr 5, 2007 at 7:40 AM // reply »
6,516 Comments

If I take out the second CFSetting, this is the output:

First Timeout!
Second Timeout!
Total Time: 3031

Looks like the second KillTime() method times out immediately, is caught, and then lets the rest of the page process (which only takes a few milliseconds).

In my experience, the "wiggle room" is generally NOT enough time to do anything much like send an email that has much of any processing time to it (ex. CFDump var="CGI").


Apr 5, 2007 at 7:40 AM // reply »
6,516 Comments

@Adam,

Ahhh, I see what you are saying now. Thanks for the clarification.


Apr 5, 2007 at 9:41 AM // reply »
64 Comments

This is an interesting piece of code.

I would have expected that setting to tell the CF server how long to wait until pulling the plug on the request (kind of what it says on the box). I would not expect it to throw a catchable exception, because it should have ceased processing the request completely.

Good to know, in an esoteric sort of way. Good work.

--
Adam


May 9, 2007 at 5:10 AM // reply »
1 Comments

<code>
<cfset thread = createObject("java", "java.lang.Thread") />
<cfset thread.sleep(5000) />
</code>


Dec 7, 2007 at 11:53 AM // reply »
1 Comments

If what you are suggesting is that the second killtime() still dies because the original requesttimeout (3 seconds) has ended and therefore the second requesttimeout (6 seconds) won't be able to update any remaining time, why does making the second timeout 60 seconds rather than 6 work (not timeout) the second killtime()?


Post Comment  |  Ask Ben

Recent Blog Comments
Nov 20, 2009 at 11:32 PM
Five Months Without Hungarian Notation And I'm Loving It
I've used headless camel case for years for not only ColdFusion variables, but also SQL tables and fields... pretty much everything involving code. I also subscribe to the "don't abbreviate and clea ... read »
Nov 20, 2009 at 11:00 PM
Five Months Without Hungarian Notation And I'm Loving It
@Marcel, Yeah, I always err on the side of longer but more readable variable names. As for the camel casing of CF methods and the headless camel casing of custom items, I get around this by always ... read »
Nov 20, 2009 at 10:56 PM
Five Months Without Hungarian Notation And I'm Loving It
I use the following and love it: my.namespace.MyComponents.functionMethodsOrUDF() CONSTANT_VALUES_OR_PROPERTIES One thing I always try is to CamelCaseBuiltInColdFusionFunctions() so others can tell ... read »
Nov 20, 2009 at 5:38 PM
Learning ColdFusion 8: CFImage Part I - Reading And Writing Images
Hi Ben, Great article. I've been looking around to see if ColdFusion image engine can programatically create the following "wrap around" effect: http://www.creativepro.com/article/photoshop-s-she ... read »
Nov 20, 2009 at 5:35 PM
Maintaining ColdFusion Sessions Across SMS Text Message Requests Without Cookies
@Dave: I talked to Gert he suggested: <cfhttp method="get" url="http://{some cf website}" result="stuff" addtoken="yes" /> Note the addition of cfhttp attribute addtoken. That should persist y ... read »
Nov 20, 2009 at 5:23 PM
Maintaining ColdFusion Sessions Across SMS Text Message Requests Without Cookies
@Todd, Ahh, gotcha, yeah that makes sense. ... read »
Nov 20, 2009 at 5:17 PM
Maintaining ColdFusion Sessions Across SMS Text Message Requests Without Cookies
Ben, sorry if I didn't make this clear. You can make it work like that if you want, just put <cfset session.foo = 1> (and <cfset application.foo = 1>) in your OnRequestStart() and it reve ... read »