7 Replies Latest reply on Aug 17, 2011 1:00 AM by Adam Cameron.

    Threads spawned by <CFTHREAD> are queued but never run

    gr8white1234

      I was having a problem with some threads spawned by <CFTHREAD> so I wrote a little test program to see if I could figure out what was going on.

       

      <cflock scope="session" type="exclusive" timeout="10">

      <cfset session.count = "0">

      </cflock>

      <cfloop from="1" to="10" index="idx">

         <cfthread name="t#idx#">

            <cflock scope="session" type="exclusive" timeout="10">

            <cfset session.count ++>

            </cflock>

         </cfthread>

      </cfloop>

      <cfset Sleep(5000)>

      <cfdump var="#session#">

       

      Spawns 10 threads each of which increments a session variable, waits a few seconds and checks the results.  As I expected the count variable was still "0".  I tried joining the threads and it just hung until the timeout expired and the variable still wasn't incremented.

       

      I assumed that meant there were some hung threads so I ran the Server Monitor.  Oddly enough it showed 0 active threads and 158 queued threads.  I reran the script above and it then showed 168 queued threads and still no active ones.  If there were hung threads shouldn't they show up as active so I could terminate them?

       

      I had CF restarted, then ran the script above and it produced the expected results (sesson.count = 10).  Checked Server Monitor, 0 active & 0 queued.  Everything back to normal.

       

      Did some more testing with my actual code and the same thing happened again.  So what is going on here?  I had CF restarted again but I'd like to figure out how this can be avoided.  If there actually are hung processes that aren't showing as active in Monitor is there any way I can kill them without having to restart CF?

       

      Any insights are appreciated.

       

      Ken

        • 1. Re: Threads spawned by <CFTHREAD> are queued but never run
          Adam Cameron. Level 5

          Dunno why you're seeing the queuing, but I also dunno why you're locking simple writes to the session scope: this is not CF5 (which was the last version of CF one needed to lock the session scope as a matter of course).  Remove the CFLOCKs and see what you get?

           

          Don't get me wrong, the locking shouldn't cause problems in your example, but equally it's just not necessary these days, so you might as well factor it out as a contributor.

           

          Let's back up a bit.  What was the original problem you were trying to diagnose?

           

          --

          Adam

          • 2. Re: Threads spawned by <CFTHREAD> are queued but never run
            gr8white1234 Level 1

            Thanks for the reply.  I've always used <CFLOCK> when writing to the session scope, having started with CF4.  But I'm certain that's not an issue here.  Anyway I can't test whether that would make any difference as right now everything is fine and I don't really want to duplicate the issue (this test script would not cause a problem in itself, it just illustrates how once whatever is happening happens, any new threads get queued but don't run).

             

            The initial issue was caused by some threads that call a cfc.  Relevant code is below:

             

            <cfif lstIMB is not "">
                 <cfobject component="cfc.IMB" name="cfcIMB">
                 <cfset cfcIMB.initialize(intTotal)>
            </cfif>
            <cfset idx = "0">
            <cfloop list="#lstIMB#" index="imb">
                 <cfthread name="Thread#++idx#" strIMB="#imb#">
                      <cftry>
                           <cfset sctIMB = cfcIMB.parse(attributes.strIMB)>
                           <cfset cfcIMB.add(sctIMB)>
                      <cfcatch>
                           <cfabort>

                      </cfcatch>
                      </cftry>
                 </cfthread>

            </cfloop>

             

            (lstIMB is a list of strings, each of which is parsed and a series of queries is executed, the results of which get put into session variables.)

            However I have tried running this code without the <cfthread> and I have also had problems with that.  So I think the underlying problem is with the cfc.  Sometimes it will process the entire list with no problem.  But when there is an error in the first item in the list (which is trapped in the cfc - all the queries have timeout limits, 5 seconds each), the process hangs.  The results of the first loop iteration show up in the session but the second one never returns.

             

            I was intrigued by your comment about cflock being unnecessary - I've heard conflicting info, the docs for CF9 (below) seem to indicate otherwise - this would seem to be the very type of application where it would be called for.

             

            ColdFusion is a multi-threaded server; it can process multiple page requests at a time. Use the cflock tag for these purposes:

            • To ensure that modifications to shared data and objects made in concurrently executing requests occur sequentially.

            • 3. Re: Threads spawned by <CFTHREAD> are queued but never run
              Adam Cameron. Level 5

              OK, well it does sound like the CFTHREAD avenue was a red herring (to mix metaphors).  Perhaps post the relevent CFC code.

               

              Re the docs: this is just a case of the docs not having been updated for (at least ~) ten years.  That's the exact same text as in the CF5 docs!  And it has not been correct since CF5.

               

              The thing is that when CF was rearchitected in Java, they wrote the session scope (and application scope, and server scope) so reads and writes to it are synchronised, so the CFLOCK equivalent is already being done for you.  When dealing with single statements, it serves absolutely no purpose, other than putting unnecessary load on the server, keeping track of all the locks.

               

              However the risk of race conditions can still occur, which do need to be protected against.  If you have more than one statement in a block of code that needs to be run atomically, then one still needs to lock it.  EG:

               

              <cfparam name="session.foo" value="0">

              <cfset sesssion.foo++>

              foo is: <cfoutput>#session.foo#</cfoutput>

               

              Two requests concurrent requests might come along and the second request might hit the second line of code before the first request runs the third line of code, meaning the first request will report "2" when one would be expecting it to say "1".  To protect against that, one needs to put a lock around that code.  Make sense?

               

              --

              Adam

              • 4. Re: Threads spawned by <CFTHREAD> are queued but never run
                gr8white1234 Level 1

                Yeah, your explanation of CFLOCK makes sense and pretty much agrees with my understanding of it.  My application does involve multiple threads reading and writing to the same session variables, granted the trivial example I posted doesn't require it.

                 

                I agree that ideally I would prevent the cfc from ever hanging but given that there is an issue with hanging threads I would really like to be able to deal with that.  I did write some code that may take care of it, a separate thread that waits for a period of time then kills any of the other threads that aren't completed.  Can't really test it see if it works as I can't cause them to hang on demand.  There doesn't seem to be any way to set a timeout when a thread is spawned to tell it to terminate after a period of time.

                 

                The CFC code is below if you want to see if you can see anything that would cause it to hang.  Note some of the tables accessed in the queries are accessed via a dblink which is a known bottleneck but I thought putting a timeout on all the queries and wrapping in a <CFTRY> block would take care of that.

                 

                 

                <cfcomponent>
                <cffunction name="initialize" access="public" returntype="void">
                <!---create a session-level struct to hold IMB results--->
                  <cfargument name="intTotal" type="numeric" required="yes">
                  <cflock scope="session" type="exclusive" timeout="5">
                  <cfset session.IMB = StructNew()>
                  <cfset session.IMB.total = intTotal>
                  <cfset session.IMB.complete = "0">
                  <cfset session.IMB.errors = "0">
                  <cfset session.IMB.results = ArrayNew(1)>
                  </cflock>
                </cffunction>
                <cffunction name="status" access="remote" returntype="struct">
                <!---get the current progress status of submitted IMBs--->
                  <cfset sctResult = StructNew()>
                  <cflock scope="session" type="readonly" timeout="5">
                  <cfif StructKeyExists(session, "IMB")>
                   <cfset sctResult.total = session.IMB.total>
                   <cfset sctResult.complete = session.IMB.complete>
                   <cfset sctResult.errors = session.IMB.errors>
                  </cfif>
                  </cflock>
                  <cfreturn sctResult>
                </cffunction>
                <cffunction name="add" access="public" returntype="boolean">
                  <cfargument name="sctIMB" type="struct" required="yes">
                  <cflock scope="session" type="exclusive" timeout="5">
                  <cfif StructKeyExists(session, "IMB")>
                   <cfset intTotal = ++ session.IMB.complete>
                   <cfif sctIMB.error is not "0">
                    <cfset session.IMB.errors ++>
                   </cfif>
                   <cfset session.IMB.results[intTotal] = sctIMB>
                   <cfset blReturn = TRUE>
                  </cfif>
                  </cflock>
                  <cfparam name="blReturn" default="#FALSE#">
                  <cfreturn blReturn>
                </cffunction>
                <cffunction name="isValid" access="public" returntype="boolean">
                  <cfargument name="input" type="string" required="yes">
                  <cfset strIMB = input>
                  <cfset reIMB = "^([0-9]{20}|[0-9]{25}|[0-9]{29}|[0-9]{31})$">
                  <cfset blResult = REFind(reIMB, strIMB)>
                  <cfreturn blResult>
                </cffunction>
                <cffunction name="Parse" access="public" returntype="struct">
                  <cfargument name="strInput" type="string" required="yes">
                  <cfset opsvisdata = "opsvis_user">
                  <cfset strIMB = strInput>
                  <cfset sctIMB = StructNew()>
                  <cfset sctIMB.input = strInput>
                  <cfif NOT REFind("^([0-9]{20}|[0-9]{25}|[0-9]{29}|[0-9]{31})$", strIMB)>
                   <!---invalid barcode - check for specific reason--->
                   <cfif NOT REFind("^.{2}[0-9]{3}", strIMB)>
                    <cfset sctIMB.error = "2"><!---non-numeric service type--->
                   <cfelseif NOT REFind("^.{5}(9[0-9]{8}|[0-8][0-9]{5})", strIMB)>
                    <cfset sctIMB.error = "4"><!---non-numeric mailer ID--->
                   <cfelseif NOT REFind("^.{5}(9.{8}[0-9]{6}|[0-8].{5}[0-9]{9})", strIMB)>
                    <cfset sctIMB.error = "5"><!---non-numeric sequence #--->
                   <cfelse>
                    <cfset sctIMB.error = "8"><!---invalid barcode length or non-numeric--->
                   </cfif>
                   <cfreturn sctIMB>
                  </cfif>
                  <cfset sctIMB.job = StructNew()>
                  <cfset intLength = Len(strIMB)>
                  <cfset sctIMB.barcodeid = Left(strIMB, 2)>
                  <cfset strSTID = Mid(strIMB, 3, 3)>
                  <cfquery name="ServiceTypeSelect" datasource="#opsvisdata#" timeout="5">
                  select SERVICE_TYPE_IND
                  from service_type_code
                  where service_type_code = <cfqueryparam value="#strSTID#">
                  </cfquery>
                  <cfif ServiceTypeSelect.RecordCount is "0">
                   <cfset sctIMB.error = "2">
                  <cfelseif ServiceTypeSelect.service_type_ind is not "F">
                   <cfset sctIMB.error = "1">
                  </cfif>
                  <cfset sctIMB.stid = strSTID>
                  <cfif Mid(strIMB, 6, 1) is "9">
                   <cfset strMID = Mid(strIMB, 6, 9)>
                   <cfset strSeq = Mid(strIMB, 15, 6)>
                  <cfelse>
                   <cfset strMID = Mid(strIMB, 6, 6)>
                   <cfset strSeq = Mid(strIMB, 12, 9)>
                  </cfif>
                  <cfset sctIMB.imbmid = strMID>
                  <cfset sctIMB.sequenceid = strSeq>
                  <cfquery name="MailerSelect" datasource="#opsvisdata#" timeout="5">
                  select mailer_name
                  from cust_reg
                  where mailer_id = <cfqueryparam value="#strMID#">
                  </cfquery>
                  <cfif MailerSelect.RecordCount is "0">
                   <cfset sctIMB.error = "3">
                   <cfset sctIMB.imbmailername = "">
                  <cfelse>
                   <cfset sctIMB.imbmailername = MailerSelect.mailer_name>
                  </cfif>
                  <cftry>
                   <cfset strQuery = "PieceSelect">
                   <cfquery name="PieceSelect" datasource="#opsvisdata#" timeout="5">
                   select job_seq_id, PHYS_CONTR_SEQ_ID container,
                   phys_hu_seq_id,
                   ML_ONR_RCPT_CRID_SEQ_ID owner,
                   ML_PREPR_RCPT_CRID_SEQ_ID preparer
                   from sasp_app.physical_piece@psasp
                   where IMB_SERIAL_NBR = <cfqueryparam cfsqltype="cf_sql_varchar" value="#strSeq#">
                   and imb_code = <cfqueryparam cfsqltype="cf_sql_varchar" value="#strIMB#">
                   </cfquery>
                   <cfif PieceSelect.job_seq_id is "">
                    <cfset strQuery = "Partition">
                    <cfquery name="PartitionSelect" datasource="#opsvisdata#" timeout="5">
                    SELECT mailer_partition_key, mid_seq_id
                    FROM sasp_app.mailer_partition_map@psasp a
                    JOIN sasp_app.mailer_id@psasp b
                    ON a.imb_mid_seq_id = b.mid_seq_id
                    WHERE mlr_id = <cfqueryparam cfsqltype="cf_sql_varchar" value="#strMID#">
                    </cfquery>
                    <cfset intKey = PartitionSelect.mailer_partition_key>
                    <cfset intMID = PartitionSelect.mid_seq_id>
                    <cfset strQuery = "PieceRange">
                    <cfquery name="PieceSelect" datasource="#opsvisdata#" timeout="5">
                    SELECT PHYS_CONTR_SEQ_ID container, phys_hu_seq_id, job_seq_id,
                    ML_ONR_RCPT_CRID_SEQ_ID owner,
                    ML_PREPR_RCPT_CRID_SEQ_ID preparer
                    FROM sasp_app.piece_range@psasp a
                    WHERE MAILER_PARTITION_KEY = <cfqueryparam value="#intKey#">
                    AND <cfqueryparam value="#strSeq#"> between TO_NUMBER(imb_lower_serial_nbr)
                    AND TO_NUMBER(imb_upper_serial_nbr)
                    AND IMB_MID_SEQ_ID = <cfqueryparam value="#intMID#">
                    </cfquery>
                    <cfset sctIMB.piecetype = "Range">
                   <cfelse>
                    <cfset sctIMB.piecetype = "Piece">
                   </cfif>
                   <cfset intJob = PieceSelect.job_seq_id>
                   <cfset intContainer = PieceSelect.container>
                   <cfset intOwner = PieceSelect.owner>
                   <cfset intPreparer = PieceSelect.preparer>
                   <cfset intTray = PieceSelect.phys_hu_seq_id>
                  <cfcatch>
                   <cfset sctIMB.error = "6">
                   <cfset sctIMB.errqry = strQuery>
                  </cfcatch>
                  </cftry>
                  <cfparam name="intJob" default="">
                  <cfif intJob is not "">
                   <cftry>
                    <cfquery name="JobSelect" datasource="#opsvisdata#" timeout="5">
                    select a.EDOC_CRID_SEQ_ID, A.JOB_NAME_TITLE_ISSUE, job_id
                    from bi_job@p2sasp a
                    where job_seq_id = <cfqueryparam value="#intJob#">
                    </cfquery>
                    <cfset intCRID = JobSelect.edoc_crid_seq_id>
                    <cfset sctIMB.job.jobid = JobSelect.job_id>
                    <cfset sctIMB.job.jobname = JobSelect.job_name_title_issue>
                   <cfcatch>
                    <cfset sctIMB.error = "6">
                    <cfset sctIMB.errqry = "Job">
                   </cfcatch>
                   </cftry>
                  </cfif>
                  <cfparam name="sctIMB.job.jobid" default="">
                  <cfparam name="sctIMB.job.jobname" default="">
                  <cfparam name="intCRID" default="">
                  <cfif intCRID is not "">
                   <cftry>
                    <cfquery name="MailerSelect" datasource="#opsvisdata#" timeout="5">
                    SELECT mlr_name mailer_name, A.CRID
                    FROM bi_opsvis_crid a
                    JOIN BI_CRID_STG cr ON TO_CHAR(a.CRID) = cr.CRID
                    WHERE crid_seq_id = <cfqueryparam value="#intCRID#">
                    </cfquery>
                    <cfset sctIMB.job.edoccrid = MailerSelect.CRID>
                    <cfset sctIMB.job.edocname = MailerSelect.mailer_name>
                   <cfcatch>
                    <cfset sctIMB.error = "6">
                    <cfset sctIMB.errqry = "Mailer">
                   </cfcatch>
                   </cftry>
                  </cfif>
                  <cfparam name="sctIMB.job.edoccrid" default="">
                  <cfparam name="sctiMB.job.edocname" default="">
                  <cfparam name="intOwner" default="">
                  <cfif intOwner is not "">
                   <cftry>
                    <cfquery name="OwnerSelect" datasource="#opsvisdata#" timeout="5">
                    SELECT mlr_name mailer_name
                    FROM bi_opsvis_crid a
                    INNER JOIN BI_CRID_STG cr ON TO_CHAR(a.CRID) = cr.CRID
                    WHERE  crid_seq_id = <cfqueryparam value="#intOwner#">
                    </cfquery>
                    <cfset sctIMB.job.ownername = OwnerSelect.mailer_name>
                   <cfcatch>
                    <cfset sctIMB.error = "6">
                    <cfset sctIMB.errqry = "Owner">
                   </cfcatch>
                   </cftry>
                  </cfif>
                  <cfparam name="sctIMB.job.ownername" default="">
                  <cfparam name="intPreparer" default="">
                  <cfif intPreparer is not "">
                   <cftry>
                    <cfquery name="PreparerSelect" datasource="#opsvisdata#" timeout="5">
                    SELECT mlr_name mailer_name
                    FROM bi_opsvis_crid a
                    INNER JOIN BI_CRID_STG cr ON TO_CHAR(a.CRID) = cr.CRID
                    WHERE  crid_seq_id = <cfqueryparam value="#intPreparer#">
                    </cfquery>
                    <cfset sctIMB.job.preprname = PreparerSelect.mailer_name>
                   <cfcatch>
                    <cfset sctIMB.error = "6">
                    <cfset sctIMB.errqry = "Preparer">
                   </cfcatch>
                   </cftry>
                  </cfif>
                  <cfparam name="sctIMB.job.preprname" default="">
                  <cfparam name="intContainer" default="">
                  <cfif intContainer is not "">
                   <cftry>
                    <cfset strQuery = "Container">
                    <cfquery name="ContainerSelect" datasource="#opsvisdata#" timeout="5">
                    select IMCB_CODE, START_THE_CLOCK_DATE, INDCTN_MTHD,
                    ACTUAL_ENTRY_DATETIME, SCHD_SHIP_DATETIME, CRITICAL_ENTRY_TIME,
                    SCAN_DATETIME, EP_PSTL_CODE, ep_fac_seq_id, excl_sts_code
                    from sasp_app.physical_container@psasp
                    where PHYS_CONTR_SEQ_ID = <cfqueryparam value="#intContainer#">
                    </cfquery>
                    <cfset sctIMB.imcb = ContainerSelect.imcb_code>
                    <cfset sctIMB.stc = ContainerSelect.start_the_clock_date>
                    <cfset sctIMB.cet = ContainerSelect.critical_entry_time>
                    <cfset sctIMB.actualentry = ContainerSelect.actual_entry_datetime>
                    <cfset sctIMB.shipdate = ContainerSelect.schd_ship_datetime>
                    <cfset sctIMB.scandate = ContainerSelect.scan_datetime>
                    <cfset sctIMB.eppstlcode = ContainerSelect.ep_pstl_code>
                    <cfset intInduct = ContainerSelect.indctn_mthd>
                    <cfset intFac = ContainerSelect.ep_fac_seq_id>
                    <cfif intFac is not "">
                     <cfset strQuery = "Facility">
                     <cfquery name="FacilitySelect" datasource="#opsvisdata#" timeout="5">
                     select fac_name, phys_state
                     from bi_facility
                     where fac_seq_id = #intFac#
                     </cfquery>
                     <cfset sctIMB.originfac = FacilitySelect.fac_name & " " & FacilitySelect.phys_state>
                    </cfif>
                    <cfif intInduct is not "">
                     <cfset strQuery = "Induction">
                     <cfquery name="InductionSelect" datasource="#opsvisdata#" timeout="5">
                     select code_desc
                     from bi_code_value_stg
                     where code_type_name = 'BIDS_INDCTN_MTHD'
                     and code_val = '#intInduct#'
                     </cfquery>
                     <cfset sctIMB.induct = InductionSelect.code_desc>
                    </cfif>
                    <cfset sctIMB.exclusion = (ContainerSelect.excl_sts_code is not "")>
                   <cfcatch>
                    <cfset sctIMB.error = "6">
                    <cfset sctIMB.errqry = strQuery>
                   </cfcatch>
                   </cftry>
                  </cfif>
                  <cfparam name="sctIMB.imcb" default="">
                  <cfparam name="sctIMB.stc" default="">
                  <cfparam name="sctIMB.cet" default="">
                  <cfparam name="sctIMB.actualentry" default="">
                  <cfparam name="sctIMB.shipdate" default="">
                  <cfparam name="sctIMB.scandate" default="">
                  <cfparam name="sctIMB.eppstlcode" default="">
                  <cfparam name="sctIMB.originfac" default="">
                  <cfparam name="sctIMB.induct" default="">
                  <cfparam name="sctIMB.exclusion" default="">
                  <cfparam name="intTray" default="">
                  <cfif intTray is not "">
                   <cftry>
                    <cfset strQuery = "Tray">
                    <cfquery name="TraySelect" datasource="#opsvisdata#" timeout="5">
                    select imtb_code, HU_LBL_CIN_CODE
                    from sasp_app.physical_hu@psasp
                    where PHYS_HU_SEQ_ID = <cfqueryparam value="#intTray#">
                     </cfquery>
                    <cfset sctIMB.imtb = TraySelect.imtb_code>
                    <cfset intCIN = TraySelect.HU_LBL_CIN_CODE>
                    <cfif intCIN is not "">
                     <cfset strQuery = "CIN">
                     <cfquery name="CINSelect" datasource="#opsvisdata#" timeout="5">
                     select code_desc
                     from BI_APP.BI_HU_CIN_CODE@p2sasp
                     where CODE_CIN = <cfqueryparam value="#intCIN#">
                     </cfquery>
                     <cfset sctIMB.cintype = CINSelect.code_desc>
                    </cfif>
                   <cfcatch>
                    <cfset sctIMB.error = "6">
                    <cfset sctIMB.errqry = strQuery>
                   </cfcatch>
                   </cftry>
                  </cfif>
                  <cfparam name="sctIMB.imtb" default="">
                  <cfparam name="sctIMB.cintype" default="">
                  <cfparam name="sctIMB.error" default="0">
                  <cfreturn sctIMB>
                </cffunction>
                <!---cffunction name="Parse1" access="remote" returntype="void">
                  <cfargument name="input" type="string" required="yes">
                  <cfset opsvisdata = "opsvis_user">
                  <cfset strIMB = input>
                  <cfset sctIMB = StructNew()>
                  <cfset sctIMB.error = "0">
                  <cfset sctIMB.input = input>
                  <cfinvoke component="IMB" method="add" sctIMB="#sctIMB#">
                </cffunction--->
                </cfcomponent>

                • 5. Re: Threads spawned by <CFTHREAD> are queued but never run
                  Adam Cameron. Level 5

                  You're not VARing any variables in there, which means all the variables that should be local to the function they're being used in, they're in the CFC's variables scope.  And given you're using a single instance of the CFC for all threads... they're going to be overrunning each other's variables.  This might not be the cause of your problem, but it is certainly going to make your code unstable.

                   

                  Sort your VARing out, and see what happens then...

                   

                  Note: you've also got a few un-paramed dynamic values hard-coded into your SQL in there, which should be attended to.  Plus I'm somewhat sceptical of manipulating the session scope directly in a CFC method.  That, however, is just a "good practice" consideration, rather than a problem with your code.

                   

                  --

                  Adam

                  1 person found this helpful
                  • 6. Re: Threads spawned by <CFTHREAD> are queued but never run
                    gr8white1234 Level 1

                    Adam, I'm really grateful that you've taken the time to share your insights.  As you may have guessed I'm new to this CFC thing (this is actually my first attempt) and I wasn't aware of the implications of not using VAR to scope the variables within a function.  You're absolutely right, the threads were overrunning each other's variables.  I believe I've fixed that.


                    Though I'm still leary of the possibility of hanging threads...the dev server hung again on Saturday and there wasn't anyone available to restart CF.  If that doesn't get resolved this can't go to production which I'm under pressure right now to do.  I'm considering a different approach where I would use CFAJAXPROXY (create a list of asynchronous calls to the CFC that would execute in the ajaxonload function).  I'm wondering if there would be an advantage to that approach or if it would create the same kinds of issues if the CFC hangs.

                     

                     

                    I'm also wondering why you think manipulating the session scope directly in a CFC method is a bad practice.  Would using the client scope be better?  What alternative would I have for ensuring the results are available for processing once the parsing is completed?  Can I somehow leverage the variables scope of the cfc?  I need to be able to produce different results for different users based on the list each one submits.

                     

                    Thanks again for your help.

                     

                    Ken

                    • 7. Re: Threads spawned by <CFTHREAD> are queued but never run
                      Adam Cameron. Level 5

                      I'd fix the VARing up and oput it live and test to see if that solves the problem, before deciding to rearchitect anything.

                       

                      Indeed perhaps the first thing to do is to load test the code in the test environment, and see if you can replicate the problem with the existing code, then fix the VARing and retest and see if it fixes it.

                       

                      As for why one shouldn't be working on the sessions cope within a CFC, it's more than one should not work with any external resource within a CFC.  As a general rule of thumb, a method's code should only access data that's been passed into it as an argument.  This improves the transportability of the code, as well as making behaviour more predictable (which makes it easier to test), and easier to maintain.

                       

                      Do a google for coding best practices or something like that, and have a read.

                       

                      That's not to say that there's no situation in which rules-of-thumb can be trumped by other considerations, but I'm not sure this is one of those examples.  YMMV.

                       

                      --
                      Adam