I wanted to post this to the community, hope it helps someone. Please
give feedback if you notice anything that could be done better.
Thanks!
Problem:
Under heavy load, we have had trouble reinitting the framework.
Recently during a large auction for one of our biggest clients, I
accidentally hit a link in my browser's URL history and fwreinit'ed
the site! Since we had so many people on the site, the reinit
actually took quite a bit of time, and a bunch of people saw error
pages. That sucked! Luis suggested a maintenance flag that would
override processColdBoxRequest() outside of ColdBox. Here is what I
came up with:
Application.cfc:
<!--- on Application Start --->
<cffunction name="onApplicationStart" returnType="boolean"
output="false">
<cfscript>
application.maintFlag = false; //maintenance flag for reinits,
bypasses processColdBoxRequest()
application.lastReinitTime = now(); //last time app was started
loadColdBox();
return true;
</cfscript>
</cffunction>
<!--- on Request Start --->
<cffunction name="onRequestStart" returnType="boolean"
output="true">
<cfargument name="targetPage" type="string" required="true" />
<cfscript>
if (not application.maintFlag or (application.maintFlag and
isDefined("url.fwreinit"))) { //allows any request with "fwreinit" to
go through, but stops anything else
reloadChecks();
if (findNoCase('index.cfm', listLast(arguments.targetPage, '/')))
{
processColdBoxRequest();
}
}
return true;
</cfscript>
</cffunction>
This sets up the maintFlag application variable and skips the
processColdBox request if it is enabled (and fwreinit is not in the
URL). I actually am sending them a nice error, but didn't include it
in this code.
Then I used 2 interceptors, preReinit and afterAspectsLoad (Notice:
preReinit is 3.0+)
<cffunction name="preReinit" output="false" access="public"
returntype="void" hint="Fires right before the reinit occurs">
<cfargument name="interceptData" required="true" type="struct"
hint="A structure containing intercepted information.">
<cfscript>
//set app to maintFlag = true
application.maintFlag = true;
</cfscript>
</cffunction>
<cffunction name="afterAspectsLoad" output="false" access="public"
returntype="void" hint="Loads after all objects are created">
<cfargument name="interceptData" required="true" type="struct"
hint="A structure containing intercepted information.">
<cfscript>
application.lastReinitTime = now(); //set last reinit time
//set app to maintFlag = false
application.maintFlag = false;
</cfscript>
</cffunction>
So basically, when you call fwreinit, the preReinit interceptor sets
maintFlag to true, then the afterAspectsLoad interceptor sets it back
to false. This single threads the application during an fwreinit, and
works really well. Now, while sending a boatload (that's more than a
buttload, but less than an assload) of hits to the site, we can reinit
to our hearts content and it works great. fwreinit is a lot faster as
well.
The only issue I currently have is that when sending a lot of hits to
a remote proxy, I will see 2 - 5 errors happen before it cleans up and
everything is working fine. Can anyone think of why the remote proxy
would act different than a "normal" event? They all go through the
application.cfc onRequestStart function.
I'm thinking possibly these requests are in the middle of being
processed when the reinit fires, so there is really no way to keep
them from happening, but I never see them in any other handler except
the remote proxy. If anyone can think of why, I would appreciate it!
The errors are:
- ColdBox Controller Not Found - The coldbox main controller has not
been initialized - The error occurred in C:\inetpub\amp\www\coldbox
\system\core\util\Util.cfc: line 128
- Element cbController is undefined in a Java object of type class
coldfusion.runtime.ApplicationScope - The error occurred in C:\inetpub
\amp\www\coldbox\system\Coldbox.cfc: line 334
- Element COLDBOXOCM is undefined in INSTANCE. - The error occurred in
C:\inetpub\amp\www\coldbox\system\web\Controller.cfc: line 109
Thanks, and hope this helps someone else in the same situation.