From f357a3145694250bf361827403252b31435afabd Mon Sep 17 00:00:00 2001 From: Marc Bachmann Date: Sun, 6 Feb 2022 03:24:34 +0100 Subject: [PATCH] fix: Reset loaded script hashes to force a reload of scripts after reconnect of redis (#1497) --- lib/redis/index.ts | 4 ++++ test/functional/pipeline.ts | 38 +++++++++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+) diff --git a/lib/redis/index.ts b/lib/redis/index.ts index 84bb672b..7b9d37f4 100644 --- a/lib/redis/index.ts +++ b/lib/redis/index.ts @@ -323,6 +323,10 @@ Redis.prototype.connect = function (callback) { // Make sure only one timer is active at a time this.clearAddedScriptHashesCleanInterval(); + // Scripts need to get reset on reconnect as redis + // might have been restarted or some failover happened + this._addedScriptHashes = {}; + // Start the script cache cleaning this._addedScriptHashesCleanInterval = setInterval(() => { this._addedScriptHashes = {}; diff --git a/test/functional/pipeline.ts b/test/functional/pipeline.ts index ff5a854f..cd0228cb 100644 --- a/test/functional/pipeline.ts +++ b/test/functional/pipeline.ts @@ -353,6 +353,44 @@ describe("pipeline", function () { }) .catch(done); }); + + it("should reload scripts on redis restart (reconnect)", async function () { + const redis = new Redis({ connectionName: "load-script-on-reconnect" }); + const redis2 = new Redis(); + redis.defineCommand("exeecafterreconnect", { + numberOfKeys: 0, + lua: `return "OK"`, + }); + + const [[err, res]] = await redis.multi([["exeecafterreconnect"]]).exec(); + expect(err).to.equal(null); + expect(res).to.equal("OK"); + + const client = await redis.client("list").then((clients) => { + const myInfo = clients + .split("\n") + .find((client) => client.includes("load-script-on-reconnect")); + + const match = / addr=([^ ]+)/.exec(myInfo); + if (match) return match[1]; + }); + + await redis2.script("flush"); + await redis2.client("kill", "addr", client); + + // Wait for reconnect, at the moment scripts are not loaded + // if the pipeline starts before ioredis reconnects + await redis.ping(); + + const [[err2, res2]] = await redis + .multi([["exeecafterreconnect"]]) + .exec(); + + expect(err2).to.equal(null); + expect(res2).to.equal("OK"); + redis.disconnect(); + redis2.disconnect(); + }); }); describe("#length", function () {