Redis Lua script implementing CAS (check-and-set)?
<p>I'm just trying to understand Redis/Lua scripting and I want to know if anyone sees a problem with the following code.</p>

<p>It's my attempt to implement very simple "CAS" semantics: call it with a single key and two arguments.  It will check to see if the value associated with that key on the server <strong>starts with</strong> first argument and, if it does, will set set the key's new value to the second argument and return 1 otherwise it will return 0; if the key is associated with some type of data other than a string then Redis will return and error just as it would if you attempted a SET command on such a key/value combination.  If the key doesn't exist prior to the call then the function will return 0 (failure).</p>

<p>Here's the script:</p>

<pre><code>local x=string.len(ARGV[1]);
if redis.call('GETRANGE', KEYS[1], 0, x-1) == ARGV[1] then
    redis.call('SET', KEYS[1], ARGV[2]);
    return 1;
    end;
return 0
</code></pre>

<p>Here's an example of calling the script on a key "foo" with a prefix value of "bar" (in the <strong><em>redis-cli</em></strong>):</p>

<pre><code>eval "local x=string.len(ARGV[1]); if redis.call('GETRANGE', KEYS[1], 0, x-1) == ARGV[1] then redis.call('SET', KEYS[1], ARGV[2]); return 1; end; return 0" 1 foo bar barbazzle
</code></pre>

<p>I think the usage pattern for this might be cases where you want to store both a "fencing token" and a value with a key ... allowing concurrent clients to attempt updates to the value if they're holding the correct fencing token.</p>

<p>Does this seem like it would be a safe usage pattern in lieu of WATCH/MULTI/EXEC semantics?  (Seems like you can fetch the current value, split off the fencing token in your local code, build a new value and then try to update the key anytime you like with semantics that seem less confusing than the WATCH/MULTI/EXEC calls).</p>

<p>(I'm aware that the semantics of my script differ slightly from the <em>memcached</em> CAS command; that's intentional).</p>

<p>This does pass my limited testing ... so I'm really asking about any potential concurrency/atomicity issues and whether there's anything stupid in the Lua --- as I've barely ever touched Lua in the past).</p>