You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

63 lines
2.5 KiB

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const crypto_1 = require("crypto");
const Command_1 = require("./Command");
const standard_as_callback_1 = require("standard-as-callback");
class Script {
constructor(lua, numberOfKeys = null, keyPrefix = "", readOnly = false) {
this.lua = lua;
this.numberOfKeys = numberOfKeys;
this.keyPrefix = keyPrefix;
this.readOnly = readOnly;
this.sha = (0, crypto_1.createHash)("sha1").update(lua).digest("hex");
const sha = this.sha;
const socketHasScriptLoaded = new WeakSet();
this.Command = class CustomScriptCommand extends Command_1.default {
toWritable(socket) {
const origReject = this.reject;
this.reject = (err) => {
if (err.message.indexOf("NOSCRIPT") !== -1) {
socketHasScriptLoaded.delete(socket);
}
origReject.call(this, err);
};
if (!socketHasScriptLoaded.has(socket)) {
socketHasScriptLoaded.add(socket);
this.name = "eval";
this.args[0] = lua;
}
else if (this.name === "eval") {
this.name = "evalsha";
this.args[0] = sha;
}
return super.toWritable(socket);
}
};
}
execute(container, args, options, callback) {
if (typeof this.numberOfKeys === "number") {
args.unshift(this.numberOfKeys);
}
if (this.keyPrefix) {
options.keyPrefix = this.keyPrefix;
}
if (this.readOnly) {
options.readOnly = true;
}
const evalsha = new this.Command("evalsha", [this.sha, ...args], options);
evalsha.promise = evalsha.promise.catch((err) => {
if (err.message.indexOf("NOSCRIPT") === -1) {
throw err;
}
// Resend the same custom evalsha command that gets transformed
// to an eval in case it's not loaded yet on the connection.
const resend = new this.Command("evalsha", [this.sha, ...args], options);
const client = container.isPipeline ? container.redis : container;
return client.sendCommand(resend);
});
(0, standard_as_callback_1.default)(evalsha.promise, callback);
return container.sendCommand(evalsha);
}
}
exports.default = Script;