From a6376cdb8a5a9a120b0e15adb5cc9037338c862c Mon Sep 17 00:00:00 2001 From: Peter Taoussanis Date: Sun, 30 Sep 2018 17:40:57 +0200 Subject: [PATCH] Experimental: Add new `hmsetnx` lua command Would be nice to have this in Redis core, but doesn't look like it's likely to happen. Ref. https://github.com/antirez/redis/issues/542 Note that there's another Lua implementation floating around (https://redisgreen.net/library/hmsetnx.html), but that doesn't account for a pre-existing hash key without the given fields. --- src/lua/hmsetnx.lua | 23 +++++++++++++++++++++++ src/taoensso/carmine.clj | 11 +++++++++++ 2 files changed, 34 insertions(+) create mode 100644 src/lua/hmsetnx.lua diff --git a/src/lua/hmsetnx.lua b/src/lua/hmsetnx.lua new file mode 100644 index 00000000..4d603fa6 --- /dev/null +++ b/src/lua/hmsetnx.lua @@ -0,0 +1,23 @@ +local hkey = KEYS[1]; + +if redis.call('exists', hkey) == 0 then + redis.call('hmset', hkey, unpack(ARGV)); + return 1; +else + local proceed = true; + for i,x in ipairs(ARGV) do + if (i % 2 ~= 0) then -- odd i => `x` is field + if redis.call('hexists', hkey, x) == 1 then + proceed = false; + break; + end + end + end + + if proceed then + redis.call('hmset', hkey, unpack(ARGV)); + return 1; + else + return 0; + end +end diff --git a/src/taoensso/carmine.clj b/src/taoensso/carmine.clj index 4d53f090..21d4fe2a 100644 --- a/src/taoensso/carmine.clj +++ b/src/taoensso/carmine.clj @@ -635,6 +635,17 @@ ;;;; +(def hmsetnx "Experimental." + (let [script (enc/slurp-resource "lua/hmsetnx.lua")] + (fn [key field value & more] + (-eval* script 1 (into [key field value] more))))) + +(comment + (wcar {} (hgetall "foo")) + (wcar {} (hmsetnx "foo" "f1" "v1" "f2" "v2"))) + +;;;; + (defn reduce-scan "For use with `scan`, `zscan`, etc. Takes: - (fn rf [acc scan-result]) -> next accumulator