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

Posted February 20, 2007 at 3:18 PM

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:

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

  • <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:

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

  • <!---
  • 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:

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

  • <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?

Download Code Snippet ZIP File

Post Comment  |  Ask Ben  |  Other Searches  |  Print Page




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

Reader Comments

Feb 20, 2007 at 4:23 PM // reply »
45 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 »
7,572 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 »
45 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 »
7,572 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 »
7,572 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 »
7,572 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...


Post Comment  |  Ask Ben

Recent Blog Comments
Mar 20, 2010 at 12:07 PM
Drawing On The iPhone Canvas With jQuery And ColdFusion
Simply awesome. Saved my day. ... read »
Mar 20, 2010 at 9:00 AM
Building A Fixed-Position Bottom Menu Bar (ala FaceBook)
I would like to say thx for an easy way to create a bottom bar. I do have a ?. Is it possible to center the bar if i want to resize it to ex 85%. Regards Offenbach ... read »
Mar 19, 2010 at 7:26 PM
MySQL 3/4 - com.mysql.jdbc.Driver And allowMultiQueries=true
Thank you very much for this post. Adding allowMultiQueries="true" in context.xml didn't help until I added it to url as allowMultiQueries=true Good idea is to use prepared statements and it will he ... read »
Jim
Mar 19, 2010 at 4:49 PM
Nobody Puts Baby In The Corner!
Wow. This is like suddenly finding a support group for your secret shame. I'm not alone! I always liked this movie, even though it is extremely cheesy. I just wish Jennifer Grey hadn't gotten the ... read »
Mar 19, 2010 at 4:47 PM
Application.cfc OnRequest() Method Affects OnError() Arguments
@Jason and @Ben, I've been doing some CF9 refactoring on our systems and noticed an odd occurrence with onError as well. Found a way to work around my problem, but what I saw was... Background: Our ... read »
Jim
Mar 19, 2010 at 4:44 PM
Shoot 'Em Up Starring Clive Owen And Paul Giamatti
I actually enjoyed this movie quite a lot. It was different, certainly, but I think they were going for more of a Quentin Tarentino-"wow, that was weird"-vibe than an actual spoof. Once I realize ... read »
Mar 19, 2010 at 4:34 PM
An Intensive Exploration Of jQuery With Ben Nadel (Video Presentation)
Hey I guess the video is down. Is there anyway you can upload to youtube or vimeo or some other service? Greatly appreciated. ... read »
Mar 19, 2010 at 4:24 PM
ColdFusion CFPOP - My First Look
@Ben Thanks for the follow up! The root of the problem had to do with being able to trace bounced emails to specific records in a DB table. Let's say you run an email campaign and you get 1,000 bou ... read »