diff --git a/README.md b/README.md index aec47b8..1a901da 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,8 @@ [![NPM](https://nodei.co/npm/koa-redis.svg?downloads=true)](https://nodei.co/npm/koa-redis/) +**v4.0.0+ now uses `ioredis` and has support for Sentinel and Cluster!** + ## Table of Contents @@ -30,8 +32,8 @@ * [session.destroy(sid)](#sessiondestroysid) * [session.quit()](#sessionquit) * [session.end()](#sessionend) + * [session.status](#sessionstatus) * [session.connected](#sessionconnected) - * [session.\_redisClient](#session_redisclient) * [session.client](#sessionclient) * [Benchmark](#benchmark) * [Testing](#testing) @@ -179,7 +181,7 @@ app.use(session({ * _all [`ioredis`](https://github.com/luin/ioredis/blob/master/API.md#new-redisport-host-options) options_ - Useful things include `url`, `host`, `port`, and `path` to the server. Defaults to `127.0.0.1:6379` * `db` (number) - will run `client.select(db)` after connection * `client` (object) - supply your own client, all other options are ignored unless `duplicate` is also supplied -* `duplicate` (boolean) - When true, it will run `client.duplicate(options)` on the supplied `client` and use all other options supplied. This is useful if you want to select a different DB for sessions but also want to base from the same client object. +* `duplicate` (boolean) - When true, it will run `client.duplicate()` on the supplied `client` and use all other options supplied. This is useful if you want to select a different DB for sessions but also want to base from the same client object. * `serialize` - Used to serialize the data that is saved into the store. * `unserialize` - Used to unserialize the data that is fetched from the store. * `isRedisCluster` (boolean) - Used for creating a Redis cluster instance per [`ioredis`][cluster] Cluster options, if set to `true`, then a new Redis cluster will be instantiated with `new Redis.Cluster(options.nodes, options.clusterOptions)` (see [Cluster docs][cluster] for more info). @@ -192,12 +194,7 @@ app.use(session({ See the [`ioredis` docs](https://github.com/luin/ioredis#connection-events) for more info. -* `ready` -* `connect` -* `reconnecting` -* `error` -* `end` -* `warning` +**Note that as of v4.0.0 the `disconnect` and `warning` events are removed as `ioredis` does not support them. The `disconnect` event is deprecated, although it is still emitted when `end` events are emitted.** ## API @@ -241,17 +238,17 @@ Generator that stops a Redis session after everything in the queue has completed Alias to `session.quit()`. It is not safe to use the real end function, as it cuts off the queue. -### session.connected +### session.status -Boolean giving the connection status updated using `client.connected` after any of the events above is fired. +String giving the connection status updated using `client.status`. -### session.\_redisClient +### session.connected -Direct access to the `ioredis` client object. +Boolean giving the connection status updated using `client.status` after any of the events above is fired. ### session.client -Direct access to the `co-redis` wrapper around the `ioredis` client. +Direct access to the `ioredis` client object. ## Benchmark diff --git a/package.json b/package.json index 003566b..9a678f5 100644 --- a/package.json +++ b/package.json @@ -17,11 +17,9 @@ ], "dependencies": { "@babel/runtime": "^7.4.3", - "co-redis": "^2.1.1", "co-wrap-all": "^1.0.0", "debug": "^4.1.1", - "ioredis": "^4.9.0", - "redis": "^2.8.0" + "ioredis": "^4.9.0" }, "devDependencies": { "@babel/cli": "^7.4.3", diff --git a/src/index.js b/src/index.js index eb3fc9d..6bafc7f 100644 --- a/src/index.js +++ b/src/index.js @@ -15,7 +15,6 @@ const util = require('util'); const { EventEmitter } = require('events'); const debug = require('debug')('koa-redis'); const Redis = require('ioredis'); -const redisWrapper = require('co-redis'); const wrap = require('co-wrap-all'); /** @@ -44,14 +43,19 @@ function RedisStore(options) { options.password || options.auth_pass || options.pass || null; // For backwards compatibility options.path = options.path || options.socket || null; // For backwards compatibility if (!options.client) { - debug('Init redis new client'); // // TODO: we should probably omit custom options we have // in this lib from `options` passed to instances below // if (options.isRedisCluster) { + debug('Initializing Redis Cluster'); + delete options.isRedisCluster; client = new Redis.Cluster(options.nodes, options.clusterOptions); } else { + debug('Initializing Redis'); + delete options.isRedisCluster; + delete options.nodes; + delete options.clusterOptions; client = new Redis(options); } } else if (options.duplicate) { @@ -76,47 +80,29 @@ function RedisStore(options) { }); } - client.on('error', this.emit.bind(this, 'error')); - client.on('end', this.emit.bind(this, 'end')); - client.on('end', this.emit.bind(this, 'disconnect')); // For backwards compatibility - client.on('connect', this.emit.bind(this, 'connect')); - client.on('reconnecting', this.emit.bind(this, 'reconnecting')); - client.on('ready', this.emit.bind(this, 'ready')); - client.on('warning', this.emit.bind(this, 'warning')); - this.on('connect', function() { - debug('connected to redis'); - this.connected = client.connected; - }); - this.on('ready', () => { - debug('redis ready'); - }); - this.on('end', function() { - debug('redis ended'); - this.connected = client.connected; - }); - // No good way to test error - /* istanbul ignore next */ - this.on('error', function() { - debug('redis error'); - this.connected = client.connected; - }); - // No good way to test reconnect - /* istanbul ignore next */ - this.on('reconnecting', function() { - debug('redis reconnecting'); - this.connected = client.connected; - }); - // No good way to test warning - /* istanbul ignore next */ - this.on('warning', function() { - debug('redis warning'); - this.connected = client.connected; + ['connect', 'ready', 'error', 'close', 'reconnecting', 'end'].forEach( + name => { + this.on(name, () => debug(`redis ${name}`)); + client.on(name, this.emit.bind(this, name)); + } + ); + + // For backwards compatibility + client.on('end', this.emit.bind(this, 'disconnect')); + + this.client = client; + + Object.defineProperty(this, 'status', { + get() { + return this.client.status; + } }); - // Wrap redis - this._redisClient = client; - this.client = redisWrapper(client); - this.connected = client.connected; + Object.defineProperty(this, 'connected', { + get() { + return ['connect', 'ready'].includes(this.status); + } + }); // Support optional serialize and unserialize this.serialize = diff --git a/test/koa-redis.test.js b/test/koa-redis.test.js index 1d93b29..586b9c7 100644 --- a/test/koa-redis.test.js +++ b/test/koa-redis.test.js @@ -12,8 +12,7 @@ */ const should = require('should'); -const redis = require('redis'); -const redisWrapper = require('co-redis'); +const Redis = require('ioredis'); function event(object, name) { // Convert events to promises @@ -24,7 +23,7 @@ function event(object, name) { describe('test/koa-redis.test.js', () => { it('should connect and ready with external client and quit ok', function*() { - const store = require('..')({ client: redis.createClient() }); + const store = require('..')({ client: new Redis() }); yield event(store, 'connect'); store.connected.should.eql(true); yield event(store, 'ready'); @@ -35,7 +34,7 @@ describe('test/koa-redis.test.js', () => { it('should connect and ready with duplicated external client and disconnect ok', function*() { const store = require('..')({ - client: redis.createClient(), + client: new Redis(), duplicate: true }); yield event(store, 'connect'); @@ -48,9 +47,8 @@ describe('test/koa-redis.test.js', () => { it('should set and delete with db ok', function*() { const store = require('..')({ db: 2 }); - let client = redis.createClient(); + const client = new Redis(); client.select(2); - client = redisWrapper(client); yield store.set('key:db1', { a: 2 }); (yield store.get('key:db1')).should.eql({ a: 2 }); JSON.parse(yield client.get('key:db1')).should.eql({ a: 2 }); diff --git a/yarn.lock b/yarn.lock index 5bea339..ffcf6bf 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2252,13 +2252,6 @@ co-mocha@^1.2.2: co "^4.0.0" is-generator "^1.0.1" -co-redis@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/co-redis/-/co-redis-2.1.1.tgz#8bc3717977c9ee5bfb6b28f39ae01bcf724d2dde" - integrity sha1-i8NxeXfJ7lv7ayjzmuAbz3JNLd4= - dependencies: - es6-promisify "^4.1.0" - co-wrap-all@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/co-wrap-all/-/co-wrap-all-1.0.0.tgz#370ae3e8333510a53f6b2f7fdfbe4568a11b7ecf" @@ -2899,23 +2892,11 @@ es-to-primitive@^1.2.0: is-date-object "^1.0.1" is-symbol "^1.0.2" -es6-promise@^3.2.1: - version "3.3.1" - resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-3.3.1.tgz#a08cdde84ccdbf34d027a1451bc91d4bcd28a613" - integrity sha1-oIzd6EzNvzTQJ6FFG8kdS80ophM= - es6-promise@^4.0.3: version "4.2.6" resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.2.6.tgz#b685edd8258886365ea62b57d30de28fadcd974f" integrity sha512-aRVgGdnmW2OiySVPUC9e6m+plolMAJKjZnQlCwNSuK5yQ0JN61DZSO1X1Ufd1foqWRAlig0rhduTCHe7sVtK5Q== -es6-promisify@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/es6-promisify/-/es6-promisify-4.1.0.tgz#dbcc1a3e93fdb8e9e709744182b7d2080c03fdb3" - integrity sha1-28waPpP9uOnnCXRBgrfSCAwD/bM= - dependencies: - es6-promise "^3.2.1" - es6-promisify@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/es6-promisify/-/es6-promisify-5.0.0.tgz#5109d62f3e56ea967c4b63505aef08291c8a5203"