Cleaner retry loop on cfquery?
Is there a cleaner or better way to do a retry loop on a flaky cfquery than something like below?
<cfset RETRY_COUNT_MAX=10>
<cfset RETRY_SLEEP_MS=3000>
<cfloop index="retryCount" from="1" to="#RETRY_COUNT_MAX#"><cftry>
<!--- do a cfquery or a cfhttp or anything that could be not work for a couple seconds --->
<cfbreak>
<cfcatch>
<cfif retryCount GTE RETRY_COUNT_MAX><cfrethrow></cfif>
<cfthread action="sleep" duration="#RETRY_SLEEP_MS#" />
</cfcatch>
</cftry></cfloop>
I do so many queries and passing of SOAP packets that I'd love some way to have code reuse. I find myself not having a (necessary) retry loop just so my code is readable.
Here's my failed attempt using Custom Tag:
<cfif (ThisTag.ExecutionMode EQ "Start")>
<cfset retry_tag_index=0>
<cfelse>
<cfset retry_tag_index=retry_tag_index+1>
<cfif retry_tag_index LTE 10>
<cfexit method="loop" />
<cfelse>
<cfexit method="exittag" />
</cfif>
</cfif>
<cfimport prefix="tags" taglib="tags">
<tags:retryOnError>
<!--- do a cfquery or a cfhttp or anything that could be not work for a couple seconds --->
</tags:retryOnError>
But although I can loop with <cfexit method="loop" />, I can't seem to figure out how to do the necessary error handling in a custom tag. I don't think it's possible. Where would one even put the cftry?
Here's my less than useful attempt with cffunction:
<cffunction name="retryOnError">
<cfargument name="fn">
<cftry>
<cfloop index="retryCount" from="1" to="#RETRY_COUNT_MAX#"><cftry>
<cfset Arguments.fn()>
<cfbreak>
<cfcatch>
<cfif retryCount GTE RETRY_COUNT_MAX><cfrethrow></cfif>
<cfthread action="sleep" duration="#RETRY_SLEEP_MS#" />
</cfcatch>
</cftry></cfloop>
</cffunction>
<cffunction name="doTheQuery">
<!--- do a cfquery or a cfhttp or anything that could be not work for a couple seconds --->
</cffunction>
<cfset retryOnError(doTheQuery)>
Why less than useful? The variables needed by the query are going to be out of scope, and passing each one would be more complicated that having a loop for each query. For example:
<cfloop query="qry">
<cfset retryOnError(doTheQuery,lots of stuff needs passed in here)>
</cfloop>
Plus you can't declare cffunction inline in code execution if you plan on using cfthread because cfthread is considered a function (what an odd implementation) and you can't declare a function in a function.
I couldn't think of anything clean to even try with cfcomponent.
Any ideas?
