Repository: luin/ioredis
Pull request #281 (2016-04-09 15:13:45)

fix(CLUSTER): fix cluster not disconnected when called disconnect method
Before this change, when disconnecting from a cluster, the nodes will be disconnected one by one. However, when the subscriber is disconnected, a new subscriber will be connected to in `-node` event, leading the cluster keeping connected.

Related issue: #277 


Patch:
diff --git a/lib/cluster/index.js b/lib/cluster/index.js
index dba62b5..926da18 100644
--- a/lib/cluster/index.js
+++ b/lib/cluster/index.js
@@ -57,7 +57,7 @@ function Cluster(startupNodes, options) {
 
   var _this = this;
   this.connectionPool.on('-node', function (redis) {
-    if (_this.subscriber === redis) {
+    if (_this.status !== 'disconnecting' && _this.subscriber === redis) {
       _this.selectSubscriber();
     }
     _this.emit('-node', redis);
@@ -193,6 +193,8 @@ Cluster.prototype.connect = function () {
  * @public
  */
 Cluster.prototype.disconnect = function (reconnect) {
+  this.setStatus('disconnecting');
+
   if (!reconnect) {
     this.manuallyClosing = true;
   }
diff --git a/lib/redis.js b/lib/redis.js
index 52e74c3..d21ef97 100644
--- a/lib/redis.js
+++ b/lib/redis.js
@@ -307,7 +307,11 @@ Redis.prototype.disconnect = function (reconnect) {
     clearTimeout(this.reconnectTimeout);
     this.reconnectTimeout = null;
   }
-  this.connector.disconnect();
+  if (this.status === 'wait') {
+    eventHandler.closeHandler(this)();
+  } else {
+    this.connector.disconnect();
+  }
 };
 
 /**
diff --git a/package.json b/package.json
index 4bba5e4..923153a 100644
--- a/package.json
+++ b/package.json
@@ -5,7 +5,7 @@
   "main": "index.js",
   "scripts": {
     "test": "NODE_ENV=test mocha",
-    "test:cov": "NODE_ENV=test DEBUG=ioredis:* node ./node_modules/istanbul/lib/cli.js cover --preserve-comments ./node_modules/mocha/bin/_mocha -- -R spec",
+    "test:cov": "NODE_ENV=test node ./node_modules/istanbul/lib/cli.js cover --preserve-comments ./node_modules/mocha/bin/_mocha -- -R spec",
     "generate-docs": "jsdoc2md lib/redis.js lib/cluster/index.js lib/commander.js > API.md",
     "build": "node tools/build > commands.js",
     "bench": "matcha benchmarks/*.js"


Test patch:
diff --git a/test/functional/cluster.js b/test/functional/cluster.js
index 8135759..d759dd5 100644
--- a/test/functional/cluster.js
+++ b/test/functional/cluster.js
@@ -1219,7 +1219,7 @@ describe('cluster', function () {
         expect(cluster.nodes('master')).to.have.lengthOf(2);
         expect(cluster.nodes('slave')).to.have.lengthOf(1);
 
-        cluster.on('-node', function () {
+        cluster.once('-node', function () {
           expect(cluster.nodes()).to.have.lengthOf(2);
           expect(cluster.nodes('all')).to.have.lengthOf(2);
           expect(cluster.nodes('master')).to.have.lengthOf(1);
diff --git a/test/functional/lazy_connect.js b/test/functional/lazy_connect.js
index 16522e5..90270aa 100644
--- a/test/functional/lazy_connect.js
+++ b/test/functional/lazy_connect.js
@@ -26,4 +26,12 @@ describe('lazy connect', function () {
       });
     });
   });
+
+  it('should be able to disconnect', function (done) {
+    var redis = new Redis({ lazyConnect: true });
+    redis.on('end', function () {
+      done();
+    });
+    redis.disconnect();
+  });
 });