I'm just trying to understand Redis/Lua scripting and I want to know if anyone sees a problem with the following code.
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 starts with 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).
Here's the script:
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
Here's an example of calling the script on a key "foo" with a prefix value of "bar" (in the redis-cli):
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
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.
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).
(I'm aware that the semantics of my script differ slightly from the memcached CAS command; that's intentional).
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).