Skip to content

Commit 7517a73

Browse files
shaharmorluin
authored andcommitted
feat: wait for ready state before resolving cluster.connect()
BREAKING CHANGE: `Cluster#connect()` will be resolved when the connection status become `ready` instead of `connect`.
1 parent 1babc13 commit 7517a73

File tree

2 files changed

+57
-24
lines changed

2 files changed

+57
-24
lines changed

lib/cluster/index.js

+28-24
Original file line numberDiff line numberDiff line change
@@ -135,13 +135,6 @@ Cluster.prototype.resetNodesRefreshInterval = function () {
135135
* @public
136136
*/
137137
Cluster.prototype.connect = function () {
138-
function readyHandler() {
139-
this.setStatus('ready');
140-
this.retryAttempts = 0;
141-
this.executeOfflineCommands();
142-
this.resetNodesRefreshInterval();
143-
}
144-
145138
var Promise = PromiseContainer.get();
146139
return new Promise(function (resolve, reject) {
147140
if (this.status === 'connecting' || this.status === 'connect' || this.status === 'ready') {
@@ -156,6 +149,14 @@ Cluster.prototype.connect = function () {
156149

157150
this.connectionPool.reset(this.startupNodes);
158151

152+
function readyHandler() {
153+
this.setStatus('ready');
154+
this.retryAttempts = 0;
155+
this.executeOfflineCommands();
156+
this.resetNodesRefreshInterval();
157+
resolve();
158+
}
159+
159160
var closeListener;
160161
var refreshListener = function () {
161162
this.removeListener('close', closeListener);
@@ -164,7 +165,7 @@ Cluster.prototype.connect = function () {
164165
if (this.options.enableReadyCheck) {
165166
this._readyCheck(function (err, fail) {
166167
if (err || fail) {
167-
debug('Ready check failed (%s). Reconnecting...', err || fail)
168+
debug('Ready check failed (%s). Reconnecting...', err || fail);
168169
if (this.status === 'connect') {
169170
this.disconnect(true);
170171
}
@@ -175,7 +176,6 @@ Cluster.prototype.connect = function () {
175176
} else {
176177
readyHandler.call(this);
177178
}
178-
resolve();
179179
};
180180

181181
closeListener = function () {
@@ -276,7 +276,7 @@ Cluster.prototype.quit = function (callback) {
276276

277277
var Promise = PromiseContainer.get();
278278
if (status === 'wait') {
279-
var ret = asCallback(Promise.resolve('OK'), callback)
279+
var ret = asCallback(Promise.resolve('OK'), callback);
280280

281281
// use setImmediate to make sure "close" event
282282
// being emitted after quit() is returned
@@ -530,9 +530,9 @@ Cluster.prototype.sendCommand = function (command, stream, node) {
530530
if (typeof to === 'function') {
531531
var nodes =
532532
nodeKeys
533-
.map(function (key) {
534-
return _this.connectionPool.nodes.all[key];
535-
});
533+
.map(function (key) {
534+
return _this.connectionPool.nodes.all[key];
535+
});
536536
redis = to(nodes, command);
537537
if (Array.isArray(redis)) {
538538
redis = utils.sample(redis);
@@ -603,7 +603,11 @@ Cluster.prototype.handleError = function (error, ttl, handlers) {
603603
timeout: this.options.retryDelayOnClusterDown,
604604
callback: this.refreshSlotsCache.bind(this)
605605
});
606-
} else if (error.message === utils.CONNECTION_CLOSED_ERROR_MSG && this.options.retryDelayOnFailover > 0 && this.status === 'ready') {
606+
} else if (
607+
error.message === utils.CONNECTION_CLOSED_ERROR_MSG &&
608+
this.options.retryDelayOnFailover > 0 &&
609+
this.status === 'ready'
610+
) {
607611
this.delayQueue.push('failover', handlers.connectionClosed, {
608612
timeout: this.options.retryDelayOnFailover,
609613
callback: this.refreshSlotsCache.bind(this)
@@ -683,16 +687,16 @@ Cluster.prototype._readyCheck = function (callback) {
683687
};
684688

685689
['sscan', 'hscan', 'zscan', 'sscanBuffer', 'hscanBuffer', 'zscanBuffer']
686-
.forEach(function (command) {
687-
Cluster.prototype[command + 'Stream'] = function (key, options) {
688-
return new ScanStream(_.defaults({
689-
objectMode: true,
690-
key: key,
691-
redis: this,
692-
command: command
693-
}, options));
694-
};
695-
});
690+
.forEach(function (command) {
691+
Cluster.prototype[command + 'Stream'] = function (key, options) {
692+
return new ScanStream(_.defaults({
693+
objectMode: true,
694+
key: key,
695+
redis: this,
696+
command: command
697+
}, options));
698+
};
699+
});
696700

697701
require('../transaction').addTransactionSupport(Cluster.prototype);
698702

test/functional/cluster/connect.js

+29
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,34 @@ describe('cluster:connect', function () {
7575
});
7676
});
7777

78+
it('should wait for ready state before resolving', function (done) {
79+
var slotTable = [
80+
[0, 16383, ['127.0.0.1', 30001]]
81+
];
82+
var argvHandler = function (argv) {
83+
if (argv[0] === 'info') {
84+
// return 'role:master'
85+
}
86+
if (argv[0] === 'cluster' && argv[1] === 'slots') {
87+
return slotTable;
88+
}
89+
if (argv[0] === 'cluster' && argv[1] === 'info') {
90+
return 'cluster_state:ok';
91+
}
92+
};
93+
var node = new MockServer(30001, argvHandler);
94+
95+
var cluster = new Redis.Cluster([
96+
{ host: '127.0.0.1', port: '30001' }
97+
], { lazyConnect: true });
98+
99+
cluster.connect().then(function () {
100+
expect(cluster.status).to.eql('ready');
101+
cluster.disconnect();
102+
disconnect([node], done);
103+
});
104+
});
105+
78106
it('should support url schema', function (done) {
79107
var node = new MockServer(30001);
80108

@@ -249,6 +277,7 @@ describe('cluster:connect', function () {
249277
expect(err.message).to.eql(errorMessage);
250278
checkDone();
251279
});
280+
252281
function checkDone() {
253282
if (!--pending) {
254283
cluster.disconnect();

0 commit comments

Comments
 (0)