I am currently on a performance crusade and have been rewriting lots of my 
current projects. One of the biggest changes as a result has been the way I 
architect my applications. I have started to use the application scope to cache 
commonly used components. For example...

===================================================================================
application.appObjs = structNew();
application.appObjs.securitySQLcfc = 
createObject("component","components.security");
application.appObjs.commomSQLcfc = 
createObject("component","components.common-sql"); 
===================================================================================

I recently posted a comment on a blog regarding this when the CF Guru himself 
Mr Sean Corfield recommend if I was going to do this, it was possible I could 
run into some thread safety issues. Now I have to be honest, I read about this 
a year or so back but never really paid attention. However it does have me 
worried a little now.  From my understanding... because I create my CFCs in the 
application scope the CFC’s are treated just like other applications vars ie. 
everyone shares it and the issue comes because this could include scopes and 
variables in CFCs not VAR-declare. The word singleton was mention, from my JAVA 
days I remember this as being an object created once but it can't be 
instantiated elsewhere in the application, well if that’s correct then that 
was my desire right?   

Ok, on the question, honest....lol

A clients website gets around 5k of traffic a day and I have already cache some 
commonly used components however this was before Mr Sean Corfield reminder on 
CFCs, Scopes & Thread Safety! I have not had any reported issues with the site. 
I am being naive or lucky? 

For example, most of the components are just simple SQL statement which I only 
want as a singleton, why create the object every time? I also don’t think 
CFCs, Scopes & Thread Safety would be an issue here, is this correct or not? 
example code...

===================================================================================
<cffunction name="getProductMenu" returntype="query" hint="returns product 
menu">
<cfquery name="productquery"  datasource="#application.appConfig.dbSource#" 
username="#application.appConfig.dbUsername#" 
password="#application.appConfig.dbPassword#">
    SELECT s.storeId, s.name as storeName, s.metaDescription as storeMeta, 
s.pos, d.depId, d.name as depName, d.metaDescription as depMeta, d.pos, c.name 
as catName, c.metaDescription as catMeta, c.catId, (SELECT COUNT(*) as proCount 
FROM products p WHERE p.catId = c.catId AND p.active != 'off') as empt
    FROM stores s
    LEFT JOIN departments d on s.storeId = d.storeId
    LEFT JOIN categories c on d.depId = c.depId
    AND (SELECT COUNT(*) as proCount FROM products p WHERE p.catId = c.catId 
AND p.active != 'off') > 0
</cfquery>
<cfreturn productquery>
</cffunction>
===================================================================================

The only one code that does concern me is my cart cfc, originally if it was in 
a include and I have only just added it to a components, yes its a little messy 
at the moment but it works. I have had not issues but if someone could look at 
it :) 

sorry it long....
===================================================================================
<cffunction name="addtoCart" access="public" hint="adds a new item to the cart">
  <!--- if cart session does not exist, create it --->
  <cfif not structkeyexists(session,"cartItem")>
    <cflock timeout="60" type="exclusive">
      <cfset session['cartItem'] = structnew()>
    </cflock>
  </cfif>
  
  <!---gets option id's from product form--->
  <cfif structkeyexists(FORM, "optVal") AND FORM['optVal'] GT 0 AND 
FORM['optVal'] NEQ ""> 
    <cfset productOptionId0 = Arraynew(1)>
    <cfset val = #form.optVal# - 1>
    <cfloop from="0" to="#val#" index=this>
      <cfset Vsel = form.sel0>
      <cfif isDefined('form.sel0')>
        <cfset formval = Evaluate("form.sel" & this)>
        <cfset optvals = ListFirst(formval,"*")>
      </cfif>
      <cfset ArrayAppend( productOptionId0, "#optvals#" ) />
    </cfloop>
    <cfset optionList = ArrayToList(productOptionId0)>
    <cfoutput> #optionList#
      <cfparam name="form.productOptionId" default="#optionList#,">
    </cfoutput>
  </cfif>
  
  
  
  <!--- if cart item does not exist, create it --->
  <cfif structkeyexists(form,"productid") and form['productid'] neq "" and 
structkeyexists(form,"qty") and form['qty'] gt 0>
    <!--- create default node for product id --->
    <cfset itemNode = "pCode_#form['productid']#_1">
    <!--- if no node exists for the given product, create it. --->
    <cfif not structkeyexists(session['cartItem'],itemNode)>
      <!--- define new node as a struct --->
      <cfset session['cartItem'][itemNode] = structnew()>
      <cfset session['cartItem'][itemNode]['aQty'] = form['qty']>
      <!--- grab the product info based on id --->
      <cfquery name="getProd" datasource="#application.appConfig.dbSource#" 
username="#application.appConfig.dbUsername#" 
password="#application.appConfig.dbPassword#">
          SELECT prodID,[name] AS pName,price,saleprice, productCode, tax
          FROM products
          WHERE prodID = #form['productid']# AND active = 'on' 
          </cfquery>
      <!--- populate the product node with info from the query, check if 
there's a sale price --->
      <cfif getProd.recordcount>
        <cfset session['cartItem'][itemNode]['proCode'] = getProd.productCode>
        <cfset session['cartItem'][itemNode]['protax'] = getProd.tax>
        <cfset session['cartItem'][itemNode]['aName'] = getProd.pName>
        <cfset session['cartItem'][itemNode]['prodId'] = #form['productid']#>
        <cfif getProd.saleprice gt 0>
          <cfset session['cartItem'][itemNode]['aPrice'] = getProd.saleprice>
          <cfelse>
          <cfset session['cartItem'][itemNode]['aPrice'] = getProd.price>
        </cfif>
      </cfif>
      <!--- if the product has options being passed, create an options node, in 
the product node --->
      <cfif structkeyexists(FORM, "optVal") AND FORM['optVal'] GT 0 AND 
FORM['optVal'] NEQ "">
        <cfset optionsList = form['productOptionId']>
        <cfset session['cartItem'][itemNode]['aOpList'] = optionsList>
        <!--- loop over option ids populate options with name and price values 
--->
        <!---|||||||||||||| CAUTION ||||||||||||||||||--->
        <!--- "optionname" was a field I added so I didn't have to join your 
other tables to get the name --->
        <!--- you'll have to create the join to grab the name here before it'll 
work --->
        <cfloop from="1" to="#listlen(optionsList)#" index="i">
          <cfset optionElem = listgetat(optionsList,i)>
          <cfset session['cartItem'][itemNode]['bOption'&optionElem] = 
structnew()>
          <cfquery name="getOptions" 
datasource="#application.appConfig.dbSource#" 
username="#application.appConfig.dbUsername#" 
password="#application.appConfig.dbPassword#">
                                                SELECT options.optionId, 
options.name, optionvalues.valueId, optionvalues.value, optionvalues.optionId, 
productoptions.valueId, productoptions.productOptionId, 
productoptions.optionPrice
                                                FROM options
                                                JOIN optionvalues ON 
options.optionId = optionvalues.optionId
                                                JOIN productoptions ON 
optionvalues.valueId = productoptions.valueId
                                                WHERE productOptionId = 
#optionElem#
                    </cfquery>
          <cfif getOptions.recordcount>
            <cfset session['cartItem'][itemNode]['bOption'&optionElem]['name'] 
= getOptions.value>
            <cfset session['cartItem'][itemNode]['bOption'&optionElem]['price'] 
= getOptions.optionPrice>
          </cfif>
        </cfloop>
      </cfif>
      <!--- check for existing cart item with options --->
      <cfelseif structkeyexists(session['cartItem'],itemNode) and 
structkeyexists(session['cartItem'][itemNode],"aOpList")>
      <cfset currentNodes = structkeylist(session['cartItem'])>
      <cfset foundNode = false>
      <!--- loop over current products in cart to see if there are any absolute 
matches --->
      <cfloop from="1" to="#listlen(currentNodes)#" index="j">
        <cfif listgetat(listgetat(currentNodes,j),2,"_") eq form['productid'] 
and 
compare(session['cartItem'][listgetat(currentNodes,j)]['aOpList'],form['productOptionId'])
 eq 0>
          <cfset itemNode = listgetat(currentNodes,j)>
          <cfset foundNode = true>
          <cfbreak>
        </cfif>
      </cfloop>
      <!--- if there's already an existing product with the same options, 
increment the qty --->
      <cfif foundNode>
        <cfset session['cartItem'][itemNode]['aQty'] = form['qty'] + 
session['cartItem'][itemNode]['aQty']>
        <!--- otherwise create a new item, increment dup item count, create new 
product node similar to above --->
        <cfelse>
        <!--- increments the unique product id if one already exists --->
        <cfset currentKeys = structkeylist(session['cartItem'])>
        <cfset focusCount = 0>
        <cfloop from="1" to="#listlen(currentKeys)#" index="x">
          <cfset focusArea = listgetat(listgetat(currentKeys,x),2,"_")>
          <cfif focusArea eq form['productid']>
            <cfset focusCount = focusCount + 1>
          </cfif>
        </cfloop>
        <cfset focusCount = focusCount + 1>
        <cfset itemNode = "pCode_#form['productid']#_#focusCount#">
        <cfset session['cartItem'][itemNode] = structnew()>
        <cfset session['cartItem'][itemNode]['aQty'] = form['qty']>
        <cfquery name="getProd" datasource="#application.appConfig.dbSource#" 
username="#application.appConfig.dbUsername#" 
password="#application.appConfig.dbPassword#">
               SELECT prodID,[name] AS pName,price,saleprice,productCode,tax
               FROM products
               WHERE prodID = #form['productid']# AND active = 'on'
               </cfquery>
        <cfif getProd.recordcount>
          <cfset session['cartItem'][itemNode]['protax'] = getProd.tax>
          <cfset session['cartItem'][itemNode]['proCode'] = getProd.productCode>
          <cfset session['cartItem'][itemNode]['aName'] = getProd.pName>
          <cfset session['cartItem'][itemNode]['prodId'] = #form['productid']#>
          <cfif getProd.saleprice gt 0>
            <cfset session['cartItem'][itemNode]['aPrice'] = getProd.saleprice>
            <cfelse>
            <cfset session['cartItem'][itemNode]['aPrice'] = getProd.price>
          </cfif>
        </cfif>
        <cfif structkeyexists(FORM, "optVal") AND FORM['optVal'] GT 0 AND 
FORM['optVal'] NEQ "">
          <cfset optionsList = form['productOptionId']>
          <cfset session['cartItem'][itemNode]['aOpList'] = optionsList>
          <cfloop from="1" to="#listlen(optionsList)#" index="i">
            <cfset optionElem = listgetat(optionsList,i)>
            <cfset session['cartItem'][itemNode]['bOption'&optionElem] = 
structnew()>
            <!---|||||||||||||| CAUTION ||||||||||||||||||--->
            <!--- "optionname" was a field I added so I didn't have to join 
your other tables to get the name --->
            <!--- you'll have to create the join to grab the name here before 
it'll work --->
            <cfquery name="getOptions" 
datasource="#application.appConfig.dbSource#" 
username="#application.appConfig.dbUsername#" 
password="#application.appConfig.dbPassword#">
                                                        SELECT 
options.optionId, options.name, optionvalues.valueId, optionvalues.value, 
optionvalues.optionId, productoptions.valueId, productoptions.productOptionId, 
productoptions.optionPrice
                                                        FROM options
                                                        JOIN optionvalues ON 
options.optionId = optionvalues.optionId
                                                        JOIN productoptions ON 
optionvalues.valueId = productoptions.valueId
                                                        WHERE productOptionId = 
#optionElem#                                                    
                         </cfquery>
            <cfif getOptions.recordcount>
              <cfset 
session['cartItem'][itemNode]['bOption'&optionElem]['name'] = getOptions.value>
              <cfset 
session['cartItem'][itemNode]['bOption'&optionElem]['price'] = 
getOptions.optionPrice>
            </cfif>
          </cfloop>
        </cfif>
      </cfif>
      <!--- if a product is already in the cart without options, just increment 
the product quantity --->
      <cfelseif structkeyexists(session['cartItem'],itemNode) and not 
structkeyexists(session['cartItem'][itemNode],"aOpList")>
      <cfset currentItemsCount = session['cartItem'][itemNode]['aQty']>
      <cfset session['cartItem'][itemNode]['aQty'] = form['qty'] + 
currentItemsCount>
    </cfif>
  </cfif>

</cffunction>

===================================================================================


If you have stuck with me this long thanks for taking time to look over this, 
looking forward to your comments :)

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~|
Adobe® ColdFusion® 8 software 8 is the most important and dramatic release to 
date
Get the Free Trial
http://ad.doubleclick.net/clk;207172674;29440083;f

Archive: 
http://www.houseoffusion.com/groups/cf-talk/message.cfm/messageid:317264
Subscription: http://www.houseoffusion.com/groups/cf-talk/subscribe.cfm
Unsubscribe: 
http://www.houseoffusion.com/cf_lists/unsubscribe.cfm?user=11502.10531.4

Reply via email to