UNPKG

@keyvhq/redis

Version:

Redis storage adapter for Keyv

80 lines (64 loc) 2.02 kB
'use strict' const Redis = require('ioredis') const { promisify } = require('util') const stream = require('stream') const { Transform } = stream const pipeline = promisify(stream.pipeline) const normalizeArguments = (input, options) => { if (input instanceof Redis) return input const { uri, ...opts } = Object.assign( typeof input === 'string' ? { uri: input } : input, options ) return new Redis(uri, opts) } class KeyvRedis { constructor (uri, options) { const redis = normalizeArguments(uri, options) this.redis = redis } async get (key) { const value = await this.redis.get(key) return value === null ? undefined : value } async set (key, value, ttl) { return typeof ttl === 'number' ? this.redis.set(key, value, 'PX', ttl) : this.redis.set(key, value) } async delete (key) { const result = await this.redis.unlink(key) return result > 0 } async clear (namespace) { const match = namespace ? `${namespace}:*` : '*' const stream = this.redis.scanStream({ match }) const unlinkKeys = new Transform({ objectMode: true, transform: (keys, _, next) => keys.length > 0 ? this.redis.unlink(keys).then(() => next()) : next() }) await promisify(pipeline)(stream, unlinkKeys) } async * iterator (namespace) { const scan = this.redis.scan.bind(this.redis) const get = this.redis.mget.bind(this.redis) async function * iterate (curs, pattern) { const [cursor, keys] = await scan(curs, 'MATCH', pattern) if (!keys.length) return const values = await get(keys) for (const i in keys) { if (Object.prototype.hasOwnProperty.call(keys, i)) { const key = keys[i] const value = values[i] yield [key, value] } } if (cursor !== '0') { yield * iterate(cursor, pattern) } } yield * iterate(0, `${namespace ? namespace + ':' : ''}*`) } } module.exports = KeyvRedis module.exports.Redis = Redis