redis-smq-common
Version:
Provides essential components and utilities shared across RedisSMQ packages.
227 lines • 8.29 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.RedisClientAbstract = exports.ELuaScriptName = void 0;
const fs_1 = __importDefault(require("fs"));
const path_1 = require("path");
const index_js_1 = require("../../async/index.js");
const index_js_2 = require("../../env/index.js");
const index_js_3 = require("../../errors/index.js");
const index_js_4 = require("../../event/index.js");
const index_js_5 = require("../errors/index.js");
const dir = index_js_2.env.getCurrentDir();
var ELuaScriptName;
(function (ELuaScriptName) {
ELuaScriptName["LPOPRPUSH"] = "LPOPRPUSH";
ELuaScriptName["ZPOPRPUSH"] = "ZPOPRPUSH";
ELuaScriptName["ZPOPLPUSH"] = "ZPOPLPUSH";
})(ELuaScriptName || (exports.ELuaScriptName = ELuaScriptName = {}));
const luaScriptMap = {
[ELuaScriptName.LPOPRPUSH]: (0, path_1.resolve)(dir, '../lua-scripts/lpoprpush.lua'),
[ELuaScriptName.ZPOPRPUSH]: (0, path_1.resolve)(dir, '../lua-scripts/zpoprpush.lua'),
[ELuaScriptName.ZPOPLPUSH]: (0, path_1.resolve)(dir, '../lua-scripts/zpoplpush.lua'),
};
const minimalSupportedVersion = [4, 0, 0];
class RedisClientAbstract extends index_js_4.EventEmitter {
constructor() {
super(...arguments);
this.connectionClosed = true;
}
init() {
index_js_1.async.series([
(cb) => this.validateRedisServerSupport(cb),
(cb) => this.loadBuiltInScriptFiles(cb),
], (err) => {
if (err)
this.emit('error', err);
else
this.emit('ready');
});
}
validateRedisVersion(major, feature = 0, minor = 0) {
if (!RedisClientAbstract.redisServerVersion) {
this.emit('error', new index_js_5.UnknownRedisServerVersionError());
return false;
}
return (RedisClientAbstract.redisServerVersion[0] > major ||
(RedisClientAbstract.redisServerVersion[0] === major &&
RedisClientAbstract.redisServerVersion[1] >= feature &&
RedisClientAbstract.redisServerVersion[2] >= minor));
}
validateRedisServerSupport(cb) {
const validate = (cb) => {
const [major, feature, minor] = minimalSupportedVersion;
if (!this.validateRedisVersion(major, feature, minor))
cb(new index_js_5.UnsupportedRedisServerVersionError());
else
cb();
};
if (!RedisClientAbstract.redisServerVersion) {
this.updateServerVersion((err) => {
if (err)
cb(err);
else
validate(cb);
});
}
else
validate(cb);
}
sscanAll(key, options, cb) {
const result = new Set();
const iterate = (cursor) => {
this.sscan(key, cursor, options, (err, reply) => {
if (err)
cb(err);
else if (!reply)
cb(new index_js_3.CallbackEmptyReplyError());
else {
reply.items.forEach((i) => result.add(i));
if (reply.cursor === '0')
cb(null, [...result]);
else
iterate(reply.cursor);
}
});
};
iterate('0');
}
hscanAll(key, options, cb) {
const result = {};
const iterate = (cursor) => {
this.hscan(key, cursor, options, (err, reply) => {
if (err)
cb(err);
else if (!reply)
cb(new index_js_3.CallbackEmptyReplyError());
else {
Object.assign(result, reply.result);
if (reply.cursor === '0')
cb(null, result);
else
iterate(reply.cursor);
}
});
};
iterate('0');
}
zpoprpush(source, destination, cb) {
this.runScript(ELuaScriptName.ZPOPRPUSH, [source, destination], [], (err, res) => {
if (err)
cb(err);
else
cb(null, typeof res === 'string' ? res : null);
});
}
zpoplpush(source, destination, cb) {
this.runScript(ELuaScriptName.ZPOPLPUSH, [source, destination], [], (err, res) => {
if (err)
cb(err);
else
cb(null, typeof res === 'string' ? res : null);
});
}
lpoprpush(source, destination, cb) {
if (this.validateRedisVersion(6, 2)) {
this.lmove(source, destination, 'LEFT', 'RIGHT', cb);
}
else {
this.runScript(ELuaScriptName.LPOPRPUSH, [source, destination], [], (err, res) => {
if (err)
cb(err);
else
cb(null, typeof res === 'string' ? res : null);
});
}
}
updateServerVersion(cb) {
if (!RedisClientAbstract.redisServerVersion) {
this.getInfo((err, res) => {
if (err)
cb(err);
else if (!res)
cb(new index_js_3.CallbackEmptyReplyError());
else {
RedisClientAbstract.redisServerVersion = res
.split('\r\n')[1]
.split(':')[1]
.split('.')
.map((i) => Number(i));
cb();
}
});
}
else
cb();
}
loadBuiltInScriptFiles(cb) {
this.loadScriptFiles(luaScriptMap, (err) => cb(err));
}
loadScriptFiles(scriptMap, cb) {
const scriptsToLoad = {};
const loadedScripts = {};
for (const name in scriptMap) {
const sha = RedisClientAbstract.scripts[name];
if (sha) {
loadedScripts[name] = sha;
}
else {
scriptsToLoad[name] = scriptMap[name];
}
}
if (Object.keys(scriptsToLoad).length === 0) {
return cb(null, loadedScripts);
}
index_js_1.async.eachIn(scriptsToLoad, (scripts, name, taskCallback) => {
const scriptsArr = Array.isArray(scripts) ? scripts : [scripts];
index_js_1.async.map(scriptsArr, (file, mapCallback) => fs_1.default.readFile(file, 'utf8', mapCallback), 10, (err, contents) => {
if (err)
return taskCallback(err);
if (!contents)
return cb(new index_js_3.CallbackEmptyReplyError());
const scriptContent = contents.join('\n');
this.loadScript(scriptContent, (err, sha) => {
if (err)
return taskCallback(err);
if (!sha)
return taskCallback(new index_js_3.CallbackEmptyReplyError());
loadedScripts[name] = sha;
RedisClientAbstract.scripts[name] = sha;
taskCallback();
});
});
}, (err) => {
if (err)
return cb(err);
cb(null, loadedScripts);
});
}
getScriptId(name) {
const id = RedisClientAbstract.scripts[name];
if (!id) {
return new index_js_3.PanicError({
message: `ID of script [${name}] is missing`,
});
}
return id;
}
runScript(scriptName, keys, args, cb) {
const sha = this.getScriptId(scriptName);
if (sha instanceof Error)
cb(sha);
else {
this.evalsha(sha, [keys.length, ...keys, ...args], (err, res) => {
if (err)
cb(err);
else
cb(null, res);
});
}
}
}
exports.RedisClientAbstract = RedisClientAbstract;
RedisClientAbstract.scripts = {};
RedisClientAbstract.redisServerVersion = null;
//# sourceMappingURL=redis-client-abstract.js.map