2

I'm using Redis with express-rate-limit and rate-limit-redis in my node ExpressJS server.

The problem I'm facing is that when my Redis server restarts (I know that is something shouldn't happen, but, let's just think it might happen eventually), it re-connects successfully, but then on the next request to my server, I get this error from Redis:

NOSCRIPT No matching script. Please use EVAL

I've read some info about it and I've seen I'm not the only one suffering from this problem.

But still, I haven't been able to find a solution.

What should I do to avoid this error? What options do I have?

EDIT: SOLUTION FOUND

So basically, when Redis is connected, I load the needed script through redisClient.scriptLoad Redis client function.

file: rate-limit.cript.lua

// Script source: https://github.com/wyattjoh/rate-limit-redis/blob/dcb5941c45325a8037bbb257882f745d9ee74b89/src/lib.ts#L58

local totalHits = redis.call("INCR", KEYS[1])
local timeToExpire = redis.call("PTTL", KEYS[1])
if timeToExpire <= 0 or ARGV[1] == "1"
then
    redis.call("PEXPIRE", KEYS[1], tonumber(ARGV[2]))
    timeToExpire = tonumber(ARGV[2])
end
return { totalHits, timeToExpire }

file: redis.js (Redis connection management)

const loadRateLimitScript = (redisClient) => redisClient.scriptLoad(
  fs.readFileSync(`${__dirname}/../constants/luaScripts/rate-limit-script.lua`, 'utf8')
    .replace(/^\s+/gm, '')
    .trim()
);


class myRedis {

  constructor() {
    const redisClient = createClient({
      url: `redis://${REDIS.HOST}:${REDIS.PORT}`
      , username: REDIS.USERNAME
      , password: REDIS.PASSWORD
    });

    redisClient.on('error', onRedisError);
    redisClient.on('connect', () => {
      loadRateLimitScript(redisClient);
    });
    redisClient.on('reconnecting', onRedisReconnecting);
    redisClient.on('ready', onRedisReady);
    redisClient.on('end', onRedisEnd);

    this.redisClient = redisClient;
  }
}
daniegarcia254
  • 1,157
  • 4
  • 17
  • 36

2 Answers2

2

NOSCRIPT No matching script. Please use EVAL

This means you are using EVALSHA to run a pre-loaded script. However, the script doesn't exist. Because when Redis restarts, all pre-loaded scripts will be removed.

In your case, rate-limit-redis might used some pre-loaded script, and these scripts have been removed when Redis restarts. So you need to take a look at the rate-limit-redis' doc to find a way to reload these scripts (SCRIPT LOAD).

for_stack
  • 21,012
  • 4
  • 35
  • 48
2

3.9.23 Update: The issue should be fixed in v3.1.0

rate-limit-redis has an open issue regarding this, and open PR that should fix it.

Eli Zatlawy
  • 678
  • 10
  • 24