views:

64

answers:

4

In my code, I am making a http request (using cfhttp) and storing the result in a variable. The http request does return results- I know this because I am logging the time of the request and the results.

However, something is apparently going wrong sometimes with storing the results of the http request (cfhttp.filecontent) in a variable, because later, when I set another variable to the first variable, the first variable is occasionally throwing an error ("Element insurance_233 is undefined in a CFML structure referenced as part of an expression."). When I dump out the session variable, the element is, sure enough, not there. I can't figure out what causes the error to occur.

Here is the code (modified slightly, but in essence enough to illustrate what I'm talking about. The trim was added in in the hopes it would solve the error. Also, I subsequently changed "inurance" & #myNum# to the more syntactically correct "insurance#myNum#", but for this illustration I left it in its original state to show how it was the last time the error was thrown.):

<cfloop query="myQuery"> <!--- one of the query columns is myNum--->
    <cflock scope="session" type="exclusive" timeout="10">
        <cfset session.report.mydata["insurance_" & #myNum#] = cfhttp.filecontent>
    </cflock>
    <cfset request.report.mydata["insurance_" & #myNum#] = trim(session.report.mydata["insurance_" & #myNum#])>
</cfloop>
+2  A: 

Unless you are using CF5 or below, you don't need to use scope locks. I don't use locks anymore unless they are named locks for a specific race condition. Also, if you lock gets to 10 seconds without the write completing, it will completely bypass the write and you won't know it. That's probably what's happening. Try adding "throwontimeout=true" to the cflock and you'll get an error when the timeout is surpassed instead of just ignoring the write.

Jason Tabler
Did you try removing the lock to see if it works?
Jason Tabler
+2  A: 

If this is in a CFC, did you write

<cfset var myNum=0>

at some point in the same method ?

Tom Chiverton
+2  A: 

You are not locking the logic that is responsible for setting the value of myNum. If multiple requests are being processed at the same time, you could end up with the following situation.

Request 1: sets myNum to 33
Request 1: writes data to session using myNum as the index; i.e. session[33]
Request 2: sets myNum to 34 
Request 1: reads data from session using myNum as the index; i.e. session[34]
Request 2: writes data to session using myNum as the index; i.e. session[34]

Thus, Request 1 attempts to read from an undefined location because Request 2 has incremented the index/myNum but has not written any data.

Lawrence Barsanti
Based on your response, I realized that the code sample I gave is not entirely accurate. myNum is really read from a query which I'm looping through...I'll modify my code. If you can, please let me know if your answer still applies.
dmr
Good question. I'm not a hundred percent but when working with CFC it is good practice to do this. <cfset var L = {}> ... <cfquery name="L.myQuery">. All variable in L will be thread safe so the situation I described cannot happen.
Lawrence Barsanti
What I ended up doing is related to what you pointed out. Instead of locking the each cfset, I placed a cflock around the entire loop. It seems to be working correctly now. Thank you!
dmr
+1  A: 

The code above doesn't give much context, but are you reading the session from the same application scope that you are writing it from?

Tyler Clendenin