0
votes

I am using a Node.JS script with the redis npm package to retrieve all the Redis keys that match a pattern animals:toFeed:*. An example of a match will be the key animals:toFeed:17ed160f59c5b31caf7e741a4e62cb7785414cd.

Using the code below, there can be 10 matches but the code will only return a few like 2-3. What might be the issue, and how can we fix it?

Using Redis 4.0.11, Node.js 8.11.3, redis 2.8.0 npm package

async function scanAsync(cursor, pattern, results) {
    return redis.scanAsync(cursor, 'MATCH', pattern, 'COUNT', '10')
        .then(function(reply) {
            cursor = reply[0]
            if(cursor === '0') {
                console.log('Scan complete')
            } else {
                console.log('Match #', i)
                let keys = reply[1]
                keys.forEach(function(key, i) {
                    results.push(key)
                })
                return scanAsync(cursor, pattern, results)
            }
        })
}

let keys = []
let prefix = 'animals:toFeed:*'
await scanAsync('0', prefix, keys) 

Update

  1. Restarted redis. Still having incomplete SCAN results
  2. Deleted all keys that matches the pattern and added some keys back. Now everything is returned when doing the SCAN. After an hour of playing, it starts returning incomplete results once more. Repeating this no longer works to fix the problem.
2

2 Answers

3
votes

You are forgetting to add keys into results when cursor equals '0', but you should always add those.

You may consider your code as follows:

async function scanAsync(cursor, pattern, results) {
    return redis.scanAsync(cursor, 'MATCH', pattern, 'COUNT', '10')
        .then(function(reply) {

            let keys = reply[1]
            keys.forEach(function(key) {
                results.push(key)
            })

            cursor = reply[0]
            if(cursor === '0') {
                console.log('Scan complete')
            } else {
                return scanAsync(cursor, pattern, results)
            }
        })
}
1
votes

… or you use redis-async-gen, which prevents you from having to carefully control all of this yourself. (Read more about it here.)

const redis = require('redis')
const client = redis.createClient(…)
const generators = require('redis-async-gen')
const { keysMatching } = generators.using(client)

const results = []
for await (const key of keysMatching('test*')) {
  results.push(key)
}