Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Redis concurrency control
const redis = require('redis');
const bluebird = require('bluebird');
const redisClient = redis.createClient({});
bluebird.promisifyAll(Object.getPrototypeOf(redisClient));
const luaScript = `
local newPayload = ARGV[1]
local newVersionStr, newData = ARGV[1]:match("^([0-9]+)|(.+)$")
local prevVal = redis.call("get", KEYS[1]) or nil
if prevVal == nil then
return redis.call("set", KEYS[1], "1|" .. newData)
end
local oldVersionStr, oldData = prevVal:match("^([0-9]+)|(.+)$")
local newVersion = tonumber(newVersionStr)
local oldVersion = tonumber(oldVersionStr)
-- check if version matches before writing
if oldVersion == (newVersion - 1) then
return redis.call('set', KEYS[1], newPayload)
else
return nil
end
`;
(async () => {
const results = await Promise.all([
redisClient.evalAsync(luaScript, 1, 'cc', '1|{a: 1}'),
redisClient.evalAsync(luaScript, 1, 'cc', '1|{b: 2}'),
redisClient.evalAsync(luaScript, 1, 'cc', '2|{b: 2}'),
]);
console.log(results); // potential output [ 'OK', null, 'OK' ]
console.log(await redisClient.getAsync('cc'));
console.log(await redisClient.delAsync('cc'));
})();
@arch1995

This comment has been minimized.

Copy link

@arch1995 arch1995 commented Apr 10, 2021

What should we do when we get null?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment