hmalphettes / redisdown

Redis backend for LevelUP
MIT License
75 stars 14 forks source link

ReplyError: NOSCRIPT No matching script. Please use EVAL. #25

Open mcollina opened 8 years ago

mcollina commented 8 years ago

Exception with:

ReplyError: NOSCRIPT No matching script. Please use EVAL.
    at parseError (/Users/matteo/Repositories/vldb-demo-levelgraph/node_modules/redisdown/node_modules/redis/node_modules/redis-parser/lib/parser.js:163:12)
    at parseType (/Users/matteo/Repositories/vldb-demo-levelgraph/node_modules/redisdown/node_modules/redis/node_modules/redis-parser/lib/parser.js:224:14)

Anybody has any clue on how to debug this?

hmalphettes commented 8 years ago

@mcollina bummer I have not seen that one before. Is this something I can reproduce?

mcollina commented 8 years ago

@hmalphettes I cannot reproduce anymore. The moment I run the unit tests of this everything started passing, and I do not know why.

I also have a situation where if I run my application, redisdown streams do not work until I run a simpler script.

I'll see if I can make a reproducible script that make this usable for me. I hoped you had an idea :(.

kanongil commented 7 years ago

I got the same error when experimenting with what happens when the redis-server is restarted. This implicitly flushes the script cache, requiring it to be reloaded.

Note that IoRedis handles it when using defineCommand(), since instead of manually loading the script, it always run EVALSHA on execution, and fallback to plain EVAL on NOSCRIPT errors. See https://github.com/luin/ioredis/blob/master/lib/script.js#L22-L33

vhf commented 7 years ago

I had the same issue and spent quite some time to find a workaround.

This problem arises, as mentioned by others here, after a redis restart.

Here's something that works:

const redisdown = require('redisdown')
const level = require('levelup')
const redis = require('redis')
const redisClient = redis.createClient()

const myThing = level('foo', {db: redisdown, redis: redisClient})

const scriptsloader = require('redisdown/scriptsloader')
redisClient.on('ready', () =>
  myThing.open(() =>
    scriptsloader.preload(redisClient, () => {})
  )
)

An alternative to this is, as mentioned, to use ioredis instead of node-redis. As simple as:

const redisdown = require('redisdown')
const level = require('levelup')
const Redis = require('ioredis')
const redisClient = Redis(opts)

const myThing = level('foo', {db: redisdown, redis: redisClient, valueEncoding: 'json'})