Dealing With RequestTimeOut And The OnError Application Event Method (Help Me)

Posted February 20, 2007 at 3:18 PM by Ben Nadel

Tags: ColdFusion

I was reading over on Dan Vega's blog this morning about request time outs when I came up with a question: How do you deal with handling time outs when your OnError() event method takes a bit of time to run? Take this simple ColdFusion example as demonstration.

First, I set up a very simple Application.cfc ColdFusion component:

  • <cfcomponent>
  •  
  • <!--- Set up global page processing. --->
  • <cfsetting
  • requesttimeout="5"
  • showdebugoutput="false"
  • />
  •  
  •  
  • <cffunction
  • name="OnError"
  • access="public"
  • returntype="void"
  • output="true">
  •  
  • <p>
  • You have errored out.
  • </p>
  •  
  • <p>
  • Error: #ARGUMENTS[ 1 ].Message#
  • </p>
  •  
  • </cffunction>
  •  
  • </cfcomponent>

This Application.cfc merely sets up the request time out for page requests and defines an OnError() event method. Then, I set up a simple page that was designed to run longer than the request time out:

  • <!---
  • Set up a bunch of CFHttp calls to force the page to
  • run longer than the set request time out.
  • --->
  • <cfhttp url="http://www.google.com?q=#Rand()#" />
  • <cfhttp url="http://www.yahoo.com?q=#Rand()#" />
  • <cfhttp url="http://www.cnn.com?q=#Rand()#" />
  • <cfhttp url="http://www.searchgalleries.com?q=#Rand()#" />
  • <cfhttp url="http://www.espn.com?q=#Rand()#" />
  • <cfhttp url="http://www.houseoffusion.com?q=#Rand()#" />
  • <cfhttp url="http://www.fullasagoog.com?q=#Rand()#" />
  • <cfhttp url="http://www.ask.com?q=#Rand()#" />
  • <cfhttp url="http://www.cnet.com?q=#Rand()#" />
  •  
  • <!--- Success! --->
  • Done grabbing content.

Since I have to get and grab the content from each of the URLs above, this should take more than the allowed five second time out. And, indeed, running that page does throw a time-out error:

You have errored out.

Error: The request has exceeded the allowable time limit Tag: cfhttp

So far, the OnError() event method works fine. But what happens when the OnError() event is not quite so simple. Let's update the event method so that it gives us more information:

  • <cffunction
  • name="OnError"
  • access="public"
  • returntype="void"
  • output="true">
  •  
  • <p>
  • You have errored out.
  • </p>
  •  
  • <p>
  • Error: #ARGUMENTS[ 1 ].Message#
  • </p>
  •  
  • <!--- Dump out the error arguments. --->
  • <cfdump
  • var="#ARGUMENTS[ 1 ]#"
  • top="1"
  • />
  •  
  • </cffunction>

Now, in addition to dumping out the error message, we are going to dump out the top level values of all argument variables. If we run the page again, we now get this error:

You have errored out.

Error: The request has exceeded the allowable time limit Tag: cfhttp

The web site you are accessing has experienced an unexpected error. Please contact the website administrator.

The request has exceeded the allowable time limit Tag: cfoutput

The error occurred in D:\...\Application.cfc: line 26

24 :
25 : <!--- Dump out the arguments. --->
26 : <cfdump var="#ARGUMENTS[ 1 ]#" top="1" />
27 :
28 : </cffunction>

As you can see, the OnError() event method is still catching the CFHttp time out, but by that time, the OnError() event method has no "request time out" left for itself to process anything.

I run into this problem a lot with CFQuery and CFExecute. Does anyway have a way to handle this more elegantly? Perhaps OnError() is not the right way to handle request time outs?




Reader Comments

Feb 20, 2007 at 4:23 PM // reply »
51 Comments

Ben,
Here are some additional thoughts. In your example you set the request timeout to 5 seconds. I understand that was for purposes of the example but lets also examine a fairly normal operation. I can see a page timeout because of the fact that it has to output so much data to a screen but what scenario is a query going to timeout like this? The default setting for a request timeout is 60 seconds. If you have queries that are taking in excess of 60 seconds on a daily basis then I think the sql needs to be examined. I know this article is a "Why & how to fix it" but I just do not see this coming up in the real world. Has this happend to you in a real world application? Just some more thoughts on the subject, great stuff though!


Feb 20, 2007 at 4:50 PM // reply »
11,243 Comments

Dan,

You are correct. This is not the most relevant real world solution. I guess the places that his happens, I can actually decrease the timeout of something like a CFExecute tag or a CFHttp tag and then if it throws an error, or if I CFTry/CFCatch the error, I can deal with it then.

In fact, on things like Reports where I have loooong running queries, this is actually how I deal with it.

I guess my concern is the "outliers" where something crazy is going on and my system attempts to log the error by it cannot do that as the logging itself takes too much time.

But that said, you are correct... this is not going to be an every day occurence. Something about it just seems strange. But I guess it makes sense. You could theoretically put an infinite loop into your OnError() method. So you need some sort of check to handle that. My gut says that it should have it's own request timeout or something.


Feb 20, 2007 at 8:46 PM // reply »
48 Comments

I asked a similar question to a great CF mind once and the response: "Don't do anything that would throw an error in your onError" -- meaning basically keep it simple. At most I'd shoot off an email in the onError method. Also a try with an empty catch should at the very least not show any exception info to your users, no?


Feb 21, 2007 at 7:32 AM // reply »
11,243 Comments

Todd,

I agree with you. I have actually found that any errors that occur in OnError() just error out and are not caught. However, the real problem here is that the error is not of a poor-programming nature; it's due to a lack of time.

I wonder if CFMail would have time to fire off. I will give that a test.


Feb 22, 2007 at 10:58 AM // reply »
1 Comments

A couple of comments.

1) According to the documentation and a bit of my testing, if an exception is thrown in the onError function, it is thrown to higher exception handlers, first <cferror...> tags then the site-wide error handler.

2) You can put plain HTML in the onError function an it will work in this situation. So one can output a simple message. I have not tried much else yet.


May 15, 2008 at 6:37 AM // reply »
1 Comments

Hi All,

I was having the same problem that you're describing and found that I could process the timeout through onError if the first thing I did in onError was to increase the timeout period.

In my case I increased the timeout in onError to 40 seconds which is 10 seconds more than is specified in the administrator. This gives me 10 seconds to handle any code (e.g. cfmail).

I know it's not very elegant but what the hell :-)

<cffunction naame="onError">

<cfsetting requesttimeout="40">

<cfmail ...>

<cfdump var="#cferror#">

</cfmail>

</cffunction>


Apr 14, 2009 at 4:19 PM // reply »
3 Comments

Hi Ben,

I know this thread hasn't been touched in almost a year, but I'm out of ideas. I can't get the TIMEOUT parameter of CFQUERY to work for the life of me. I'm using CFMX 7.0.2 with MS SQL Server 2005. This is what I run:

<cfquery name="test" datasource="dsn" timeout="1">
select top 20000 *
from table </cfquery>

<cfoutput>#cfquery.ExecutionTime#</cfoutput>

That query outputs a number that's in the 3000s -- which should never happen, right? Since the timeout is set for 1 second (or 1000ms). Why is this happening? I thought the TIMEOUT paramter works with SQL...


Apr 14, 2009 at 7:22 PM // reply »
11,243 Comments

@Sung,

I didn't even know the CFQuery tag had a timeout attribute :) If this is not working, it's probably a driver issue. Maybe this only works for certain types of datasources.


Apr 14, 2009 at 7:29 PM // reply »
3 Comments

Hi Ben,

It's news to me, too -- I didn't realize CFQUERY had a timeout param, either, until today. But I've scoured the net every which way, and it seems like there are a bunch of folks who say this works for JDBC drivers that hook into MS SQL. Which is exactly my setup, so I just don't get it.

I can't even use CFSETTING here. Because if the datasource is unresponsive, even if you have CFSETTING's REQUESTTIMEOUT set to 30 seconds, the page will not time out at the 30-second mark because this is an external action (like CFHTTP). It'll just keep waiting, and when the datasource finally fails, then the CFSETTING will kick in immediately. It's actually quite useless.


Apr 15, 2009 at 8:10 AM // reply »
11,243 Comments

@Sung,

From what I understand from my own experience, CFSetting only comes into play when control is back in the ColdFusion workflow. So, if a query is taking too long to run, the page won't timeout until the query returns and then ColdFusion tries to take a next action.


Apr 15, 2009 at 8:22 AM // reply »
3 Comments

@Ben Nadel, yup, I understand it the same way. That's why the TIMEOUT parameter in CFQUERY is really the only way to handle this -- except it just plain isn't working. It's frustrating...


Nov 11, 2010 at 9:42 PM // reply »
2 Comments

Hi Ben -any chance you have figured this out ? I am simply trying to loop over 5k records and append the key field to a list. it tiems out every time :(
Just hoping you figured out something.
thanks and God Bless
Chris


Nov 13, 2010 at 11:46 AM // reply »
11,243 Comments

@Chris,

For pages that I know are going to run a long time, I use a larger timeout (via the CFSetting tag). If the onError() does get fired, I typically include *another* CFSetting tag that increases the page timeout in order to allow the error-processing to take place.


bah
Jan 23, 2011 at 8:10 PM // reply »
1 Comments

came across yer article and remembered this post from many moons ago - not many of the timeouts on cf are actually obeyed until the request completes. (Server: sorry about that request you submitted about 10 mins ago, but it told me that if it ran for more than 1 min, I should tell u it failed!)

http://forums.adobe.com/thread/264691?tstart=0



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 23, 2013 at 11:06 AM
Strange Interaction Between DeserializeJson(), ArrayContains(), And Database Values In ColdFusion
@Ben, Are you talking about As Number: YES As String: YES As Java: YES? If so, that's with 3 different ways of referencing the constant 1, not users.id[1]. Query object references(*) are what seem ... read »
May 23, 2013 at 9:55 AM
Strange Interaction Between DeserializeJson(), ArrayContains(), And Database Values In ColdFusion
@Dan, According to the CF Admin, I'm running Java "1.6.0_45". As far as the DB column, in the database it's an INT. I'll see if I can dig into what CF sees it as. @WebManWalking, But h ... read »
May 23, 2013 at 9:49 AM
Strange Interaction Between DeserializeJson(), ArrayContains(), And Database Values In ColdFusion
@Ben, I think the problem is that we're used to loose typing in ColdFusion, like JavaScript. If a value is a number but it's needed in an expression to be a string, noooo problem. I've encountered ... read »
May 23, 2013 at 9:47 AM
ColdFusion QueryAppend( qOne, qTwo )
You rock! Thank you, thank you, thank you!!! ... read »
May 23, 2013 at 5:19 AM
Ask Ben: Print Part Of A Web Page With jQuery
How to print also the background color of table cells and table lines ... read »
May 23, 2013 at 3:55 AM
Javascript Array Methods: Unshift(), Shift(), Push(), And Pop()
very interesting and helpful too. ... read »
May 22, 2013 at 5:35 PM
Script Tags, jQuery, And Html(), Text() And Contents()
This is still an issue 2 years later. jQuery is supposed to remediate these cross browser issues, no? I have been unable to find any statement from the jQuery team calling this behavior "by de ... read »
May 22, 2013 at 12:44 PM
Ask Ben: Query Loop Inside CFScript Tags
In cf10, if you call a function that has: local.result = {}; local.result.msg = ""; local.svc = new query(); local.svc.setSQL("SELECT * FROM..."); local.obj = local.svc.exe ... read »
InVision App - Prototyping Made Beautiful With Prototyping Tools