From f0c600be8ee5edaa1f24d64ff512f507dab04741 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=AD=90=E9=AA=85?= Date: Sat, 30 Jun 2018 11:29:06 +0800 Subject: [PATCH] feat: `Redis#connect()` will be resolved when status is ready (#648) BREAKING CHANGE: `Redis#connect()` will be resolved when status is ready instead of `connect`: ``` const redis = new Redis({ lazyConnect: true }) redis.connect().then(() => { assert(redis.status === 'ready') }) ``` --- API.md | 12 +++++++---- lib/redis.js | 32 ++++++++++++++++------------ test/functional/connection.js | 40 ++++++++++++++++++++++++++++++++++- 3 files changed, 66 insertions(+), 18 deletions(-) diff --git a/API.md b/API.md index f77ff538..8d8072dc 100644 --- a/API.md +++ b/API.md @@ -18,7 +18,7 @@ * [Redis](#Redis) ⇐ [EventEmitter](http://nodejs.org/api/events.html#events_class_events_eventemitter) * [new Redis([port], [host], [options])](#new_Redis_new) * _instance_ - * [.connect([callback])](#Redis+connect) ⇒ Promise + * [.connect([callback])](#Redis+connect) ⇒ Promise.<void> * [.disconnect()](#Redis+disconnect) * ~~[.end()](#Redis+end)~~ * [.duplicate()](#Redis+duplicate) @@ -68,7 +68,6 @@ Creates a Redis instance var Redis = require('ioredis'); var redis = new Redis(); -// or: var redis = Redis(); var redisOnPort6380 = new Redis(6380); var anotherRedis = new Redis(6380, '192.168.100.1'); @@ -80,9 +79,13 @@ var authedRedis = new Redis(6380, '192.168.100.1', { password: 'password' }); ``` -### redis.connect([callback]) ⇒ Promise +### redis.connect([callback]) ⇒ Promise.<void> Create a connection to Redis. -This method will be invoked automatically when creating a new Redis instance. +This method will be invoked automatically when creating a new Redis instance +unless `lazyConnect: true` is passed. + +When calling this method manually, a Promise is returned, which will +be resolved when the connection status is ready. **Kind**: instance method of [Redis](#Redis) **Access**: public @@ -234,6 +237,7 @@ Creates a Redis Cluster instance | [options.retryDelayOnClusterDown] | number | 100 | When a CLUSTERDOWN error is received, client will retry if `retryDelayOnClusterDown` is valid delay time. | | [options.retryDelayOnTryAgain] | number | 100 | When a TRYAGAIN error is received, client will retry if `retryDelayOnTryAgain` is valid delay time. | | [options.slotsRefreshTimeout] | number | 1000 | The milliseconds before a timeout occurs while refreshing slots from the cluster. | +| [options.slotsRefreshInterval] | number | 5000 | The milliseconds between every automatic slots refresh. | | [options.redisOptions] | Object | | Passed to the constructor of `Redis`. | diff --git a/lib/redis.js b/lib/redis.js index fc5addd5..c9cf2c06 100644 --- a/lib/redis.js +++ b/lib/redis.js @@ -239,9 +239,13 @@ Redis.prototype.setStatus = function (status, arg) { /** * Create a connection to Redis. - * This method will be invoked automatically when creating a new Redis instance. + * This method will be invoked automatically when creating a new Redis instance + * unless `lazyConnect: true` is passed. + * + * When calling this method manually, a Promise is returned, which will + * be resolved when the connection status is ready. * @param {function} [callback] - * @return {Promise} + * @return {Promise} * @public */ Redis.prototype.connect = function (callback) { @@ -253,9 +257,11 @@ Redis.prototype.connect = function (callback) { } this.setStatus('connecting'); + const {options} = this; + this.condition = { - select: this.options.db, - auth: this.options.password, + select: options.db, + auth: options.password, subscriber: false }; @@ -268,11 +274,11 @@ Redis.prototype.connect = function (callback) { _this.setStatus('end'); return; } - var CONNECT_EVENT = _this.options.tls ? 'secureConnect' : 'connect'; + var CONNECT_EVENT = options.tls ? 'secureConnect' : 'connect'; _this.stream = stream; - if (typeof _this.options.keepAlive === 'number') { - stream.setKeepAlive(true, _this.options.keepAlive); + if (typeof options.keepAlive === 'number') { + stream.setKeepAlive(true, options.keepAlive); } stream.once(CONNECT_EVENT, eventHandler.connectHandler(_this)); @@ -280,8 +286,8 @@ Redis.prototype.connect = function (callback) { stream.once('close', eventHandler.closeHandler(_this)); stream.on('data', eventHandler.dataHandler(_this)); - if (_this.options.connectTimeout) { - stream.setTimeout(_this.options.connectTimeout, function () { + if (options.connectTimeout) { + stream.setTimeout(options.connectTimeout, function () { stream.setTimeout(0); stream.destroy(); @@ -296,19 +302,19 @@ Redis.prototype.connect = function (callback) { }); } - if (_this.options.noDelay) { + if (options.noDelay) { stream.setNoDelay(true); } - var connectionConnectHandler = function () { + var connectionReadyHandler = function () { _this.removeListener('close', connectionCloseHandler); resolve(); }; var connectionCloseHandler = function () { - _this.removeListener(CONNECT_EVENT, connectionConnectHandler); + _this.removeListener('ready', connectionReadyHandler); reject(new Error(utils.CONNECTION_CLOSED_ERROR_MSG)); }; - _this.once(CONNECT_EVENT, connectionConnectHandler); + _this.once('ready', connectionReadyHandler); _this.once('close', connectionCloseHandler); }, function (type, err) { _this.silentEmit(type, err); diff --git a/test/functional/connection.js b/test/functional/connection.js index 9301d77d..fb033d03 100644 --- a/test/functional/connection.js +++ b/test/functional/connection.js @@ -96,7 +96,9 @@ describe('connection', function () { it('should stop reconnecting when disconnected', function (done) { var redis = new Redis(8999, { - retryStrategy: function () { return 0; } + retryStrategy: function () { + return 0; + } }); redis.on('close', function () { @@ -116,6 +118,42 @@ describe('connection', function () { done(); }); }); + + it('should resolve when the status become ready', function (done) { + var redis = new Redis({ lazyConnect: true }); + redis.connect().then(function () { + expect(redis.status).to.eql('ready'); + done(); + }); + }); + + it('should reject when closed (reconnecting)', function (done) { + var redis = new Redis({ + port: 8989, + lazyConnect: true, + retryStrategy: function () { + return 0; + } + }); + + redis.connect().catch(function () { + expect(redis.status).to.eql('reconnecting'); + done(); + }); + }); + + it('should reject when closed (end)', function (done) { + var redis = new Redis({ + port: 8989, + lazyConnect: true, + retryStrategy: false + }); + + redis.connect().catch(function () { + expect(redis.status).to.eql('end'); + done(); + }); + }); }); describe('retryStrategy', function () {