0.2.5 • Published 7 years ago

scan-llen v0.2.5

Weekly downloads
6
License
ISC
Repository
github
Last release
7 years ago

scan-llen

Containerized utility to scan and print llen of Redis keys.

Use case

We wish to scan keys in Redis using a specified pattern, and print the lengths of the list keys.

$ docker build -t scan-llen https://github.com/evanx/scan-llen.git
$ docker run -i --rm --network=host -e pattern='*' scan-llen
12 list1
5 list2

Config

See lib/config.js

module.exports = {
    description: 'Containerized utility to scan and print llen of Redis keys.',
    required: {
        pattern: {
            description: 'the matching pattern for Redis scan',
            example: '*'
        },
        limit: {
            description: 'the maximum number of keys to print',
            default: 10,
            note: 'zero means unlimited'
        },
        host: {
            description: 'the Redis host',
            default: 'localhost'
        },
        port: {
            description: 'the Redis port',
            default: 6379
        }
    }
}

Docker test

See bin/test.sh https://github.com/evanx/scan-llen/blob/master/bin/test.sh

This builds:

  • isolated network scan-llen-network
  • isolated Redis instance named scan-llen-redis
  • this utility evanx/scan-llen

We populate our test keys:

populate() {
  redis-cli -h $redisHost lpush list1 1 | grep -q '^1$'
  redis-cli -h $redisHost lpush list2 1 | grep -q '^1$'
  redis-cli -h $redisHost lpush list2 2 | grep -q '^2$'
}

We build a container image for this service:

docker build -t scan-llen https://github.com/evanx/scan-llen.git

We interactively run the service on our test Redis container:

docker run --name scan-llen-instance --rm -i \
  --network=scan-llen-network \
  -e host=$redisHost \
  -e pattern='*' \
  scan-llen

Implementation

See lib/main.js

    let cursor;
    while (true) {
        const [result] = await multiExecAsync(client, multi => {
            multi.scan(cursor || 0, 'match', config.pattern);
        });
        cursor = parseInt(result[0]);
        const keys = result[1];
        const types = await multiExecAsync(client, multi => {
            keys.forEach(key => multi.type(key));
        });
        const listKeys = keys.filter((key, index) => types[index] === 'list');
        if (listKeys.length) {
            count += listKeys.length;
            const results = await multiExecAsync(client, multi => {
                listKeys.forEach(key => multi.llen(key));
            });
            listKeys.forEach((key, index) => {
                const result = results[index];
                console.log(key, result);
            });
            if (config.limit > 0 && count > config.limit) {
                console.error(clc.yellow('Limit exceeded. Try: limit=0'));
                break;
            }
        }
        if (cursor === 0) {
            break;
        }
    }

Appication archetype

Incidently lib/index.js uses the redis-app-rpf application archetype.

require('redis-app-rpf')(require('./spec'), require('./main'));

where we extract the config from process.env according to the spec and invoke our main function.

See https://github.com/evanx/redis-app-rpf.

This provides lifecycle boilerplate to reuse across similar applications.

0.2.5

7 years ago

0.2.4

7 years ago

0.2.3

7 years ago

0.2.2

7 years ago

0.2.1

7 years ago

0.2.0

7 years ago

0.1.0

7 years ago