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 »
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 »
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 »
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
Comments (6) | Post Comment | Ask Ben | Permalink | Other Searches | Print Page
Reinventing The Wheel As A Reflection Of Skill Level (RE: Mark Mandel)
ColdFusion Method Attribute Output=True Does Not Jive With EnableCFOutputOnly
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!
Posted by Dan on Feb 20, 2007 at 4:23 PM
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.
Posted by Ben Nadel on Feb 20, 2007 at 4:50 PM
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?
Posted by todd sharp on Feb 20, 2007 at 8:46 PM
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.
Posted by Ben Nadel on Feb 21, 2007 at 7:32 AM
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.
Posted by Ian Skinner on Feb 22, 2007 at 10:58 AM
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>
Posted by J Wilson on May 15, 2008 at 6:37 AM