Ask a Jedi: CFLOCK in CFSCRIPT?

Heinz asks:

I saw that you have generated substitutions to user CF-tags in CFSCRIPT [at CFLIB]. My problem: I want to have a substitute for CFLOCK but CFLOCK has a start- and a end-tag! Do you have a hint to solve this?

So, what Heinz is talking about is a set of UDFs I built that allow you to call CF tags in CFSCRIPT. You can find an entire library of them called CFMLLib. One example is WDDXSerialize. It allows you do stuff like this:

<FONT COLOR=MAROON><cfscript></FONT>
x = arrayNew(<FONT COLOR=BLUE>1</FONT>);
x[1] = now();
x[2] = structNew();
x[2].foo = <FONT COLOR=BLUE>"goo"</FONT>;
packet = wddxSerialize(x);
writeOutput(left(htmlEditFormat(packet),<FONT COLOR=BLUE>100</FONT>));
<FONT COLOR=MAROON></cfscript></FONT>

However, as Heinz points out, there is no way to duplicate the concept of locking, since locking involves wrapping a set of commands. So the short answer is - he is right. However, one of the best things about ColdFusion is that there is multiple ways to solve a problem.

Let’s say you want to access a value in the Application scope, but others may access it as well, so you want to have a ReadOnly lock when reading it, and an exclusive lock when writing it. How about a simple UDF?

<FONT COLOR=MAROON><cffunction name=<FONT COLOR=BLUE>"scopeLockRead"</FONT> output=<FONT COLOR=BLUE>"false"</FONT> returnType=<FONT COLOR=BLUE>"any"</FONT>></FONT>
   <FONT COLOR=MAROON><cfargument name=<FONT COLOR=BLUE>"scope"</FONT> type=<FONT COLOR=BLUE>"string"</FONT> required=<FONT COLOR=BLUE>"true"</FONT>></FONT>
   <FONT COLOR=MAROON><cfargument name=<FONT COLOR=BLUE>"key"</FONT> type=<FONT COLOR=BLUE>"string"</FONT> required=<FONT COLOR=BLUE>"true"</FONT>></FONT>
   <FONT COLOR=MAROON><cfargument name=<FONT COLOR=BLUE>"timeout"</FONT> type=<FONT COLOR=BLUE>"numeric"</FONT> required=<FONT COLOR=BLUE>"false"</FONT> default=<FONT COLOR=BLUE>"30"</FONT>></FONT>
   <FONT COLOR=MAROON><cfset var ptr = <FONT COLOR=BLUE>""</FONT>></FONT>
   
   <FONT COLOR=MAROON><cflock scope=<FONT COLOR=BLUE>"#arguments.scope#"</FONT> type=<FONT COLOR=BLUE>"readOnly"</FONT> timeout=<FONT COLOR=BLUE>"#arguments.timeout#"</FONT>></FONT>
      <FONT COLOR=MAROON><cfset ptr = structGet(arguments.scope)></FONT>
      <FONT COLOR=MAROON><cfreturn duplicate(ptr[arguments.key])></FONT>
   <FONT COLOR=MAROON></cflock></FONT>
<FONT COLOR=MAROON></cffunction></FONT>

<FONT COLOR=MAROON><cffunction name=<FONT COLOR=BLUE>"scopeLockWrite"</FONT> output=<FONT COLOR=BLUE>"false"</FONT> returnType=<FONT COLOR=BLUE>"void"</FONT>></FONT>
   <FONT COLOR=MAROON><cfargument name=<FONT COLOR=BLUE>"scope"</FONT> type=<FONT COLOR=BLUE>"string"</FONT> required=<FONT COLOR=BLUE>"true"</FONT>></FONT>
   <FONT COLOR=MAROON><cfargument name=<FONT COLOR=BLUE>"key"</FONT> type=<FONT COLOR=BLUE>"string"</FONT> required=<FONT COLOR=BLUE>"true"</FONT>></FONT>
   <FONT COLOR=MAROON><cfargument name=<FONT COLOR=BLUE>"value"</FONT> type=<FONT COLOR=BLUE>"any"</FONT> required=<FONT COLOR=BLUE>"true"</FONT>></FONT>
   <FONT COLOR=MAROON><cfargument name=<FONT COLOR=BLUE>"timeout"</FONT> type=<FONT COLOR=BLUE>"numeric"</FONT> required=<FONT COLOR=BLUE>"false"</FONT> default=<FONT COLOR=BLUE>"30"</FONT>></FONT>
   <FONT COLOR=MAROON><cfset var ptr = <FONT COLOR=BLUE>""</FONT>></FONT>
   
   <FONT COLOR=MAROON><cflock scope=<FONT COLOR=BLUE>"#arguments.scope#"</FONT> type=<FONT COLOR=BLUE>"exclusive"</FONT> timeout=<FONT COLOR=BLUE>"#arguments.timeout#"</FONT>></FONT>
      <FONT COLOR=MAROON><cfset ptr = structGet(arguments.scope)></FONT>
      <FONT COLOR=MAROON><cfset ptr[arguments.key] = arguments.value></FONT>
   <FONT COLOR=MAROON></cflock></FONT>
<FONT COLOR=MAROON></cffunction></FONT>
      
<FONT COLOR=MAROON><cfscript></FONT>
scopeLockWrite(<FONT COLOR=BLUE>"server"</FONT>,<FONT COLOR=BLUE>"counter"</FONT>,<FONT COLOR=BLUE> 100</FONT>);
writeOutput(scopeLockRead(<FONT COLOR=BLUE>"server"</FONT>,<FONT COLOR=BLUE>"counter"</FONT>));
<FONT COLOR=MAROON></cfscript></FONT>

This example presents two UDFs. The first, scopeLockRead, will perform a locked read on the requested scope. The second one will do an update. Now - this doesn’t give you exactly what you want, but it may be useful.

Another thing to consider. If your operation needs to be locked and you want to call the operation from cfscript, simply put the entire operation, including the locks, in a UDF. Don’t forget that a UDF need not be a “generic utility”, it could be very specific to your application. Once you have wrapped it up into a UDF, then you could easily call it from CFSCRIPT.

Anyone else have thoughts on this?

Raymond Camden's Picture

About Raymond Camden

Raymond is a developer advocate. He focuses on JavaScript, serverless and enterprise cat demos. If you like this article, please consider visiting my Amazon Wishlist or donating via PayPal to show your support.

Lafayette, LA https://www.raymondcamden.com

Comments