Desdoyer
Desdoyer

Reputation: 82

null null error in SERVER structure

I have a SERVER variable, a structure of structures, which is highly accessed by all users (concurrency). Values are added and deleted very very frequently. Here is a small example of my SERVER variable. The real one has much more data.

<cfset SERVER.structure = StructNew()>

<cfset s = StructNew()>
<cfset StructInsert(s, 'test11', 'value11', true)>
<cfset StructInsert(s, 'test12', 'value12', true)>
<cfset StructInsert(SERVER.structure, 'test1', s, true)>

<cfset s = StructNew()>
<cfset StructInsert(s, 'test21', 'value21', true)>
<cfset StructInsert(s, 'test22', 'value22', true)>
<cfset StructInsert(SERVER.structure, 'test2', s, true)>

Every couple of hours, I loop this structure to clean expired data. However, I am getting the error "null null" while looping the variable like this:

<cfloop collection="#SERVER.structure#" item="key">
    <cfif StructKeyExists(SERVER.structure, key)>
        <cfloop collection="#StructFind(SERVER.structure, key)#" item="key2">
            <!--- And some code here --->
        </cfloop>
    </cfif>

    <cfif StructCount(StructFind(SERVER.structure, key)) eq 0>
        <cfset StructDelete(SERVER.structure, key, false)>
    </cfif>
</cfloop>

I'm receiving the error in the first line of the example. In this line, exactly:

<cfloop collection="#SERVER.structure#" item="key">

So I tried another approach. Instead of looping one by one, I created an array of keys and looped it. Unfortunately, the "null null" error was also happening there, in this exact line:

<cfset arrayOfKeys = StructKeyArray(SERVER.structure)>

My first theory is that ColdFusion can't handle the concurrency level that this SERVER variable has. I tried to use a <cflock> here, while clearing the variable, but it didn't work either. And I can't have this <cflock> where the variable is actually being used and modified by users because of the extra load that it would add (I believe).

I don't know... I'm out of ideas. Does anyone now why is this happening or have suffered this problem before? And a solution or workaround to this problem, or even a suggestion to make my code better, would be more than welcome too.

Thank you very much.

Upvotes: 0

Views: 284

Answers (1)

Adam Cameron
Adam Cameron

Reputation: 29870

I tried to use a <cflock> here, while clearing the variable, but it didn't work either. And I can't have this <cflock> where the variable is actually being used and modified by users because of the extra load that it would add (I believe).

This is your problem. If you are using the server scope, you must lock all access to it (read and write). Otherwise you will get errors. That's the long and the short of it.

My first theory is that ColdFusion can't handle the concurrency level that this SERVER variable has

Well: no. ColdFusion will synchronise individual operations to the server scope (well: it's handled at Java level), and that's where its job begins and ends. It's just that your approach doesn't handle it. Namely that you don't take steps to mitigate race conditions in your own code. This assertion of yours:

I am not locking access when I work with the variable because collisions can't happen

Is just wrong. There's a race condition in your loop.

As others have hinted at, this is very poor application architecture, and the code is facile.

Just put the data in a database. That's what databases are for, and they're written in such a way to optimise the sorts of operation you are trying to (but not succeeding, obviously) to achieve here.

I think this is probably a case of premature optimisation: have you had this data in a properly provisioned and designed DB? Or are you second-guessing that it will be a problem? I suspect it's the latter. Or that the DB server was not properly provisioned.

Over and above the database tier, you could also use a caching tier like others have suggested.

But just don't reinvent the wheel, like others have said.

The bottom line answer to your question is that you're getting the errors because you are not correctly locking the data, and you have race conditions in your code, making ColdFusion trying to access data that you have told it is there, but could subsequently have been changed. This is due to your code, not a shortcoming in ColdFusion.

Upvotes: 1

Related Questions