Skip to content

Commit 90c950d

Browse files
author
Derek Bredensteiner
committed
Add disable_flush option for sentinel queue commands. Also makes sentinel connect to a dummy server to start.
1 parent d0be9ac commit 90c950d

File tree

2 files changed

+43
-39
lines changed

2 files changed

+43
-39
lines changed

index.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,11 @@ RedisClient.prototype.initialize_retry_vars = function () {
126126

127127
// flush offline_queue and command_queue, erroring any items with a callback first
128128
RedisClient.prototype.flush_and_error = function (message) {
129+
130+
if (this.options.disable_flush) {
131+
return;
132+
}
133+
129134
var command_obj;
130135
while (this.offline_queue.length > 0) {
131136
command_obj = this.offline_queue.shift();

lib/sentinel.js

Lines changed: 38 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ function RedisSentinelClient(options) {
3232

3333
this.options.masterName = this.options.masterName || 'mymaster';
3434

35+
self.emitMasterErrors = false;
36+
3537
// no socket support for now (b/c need multiple connections).
3638
if (options.port == null || options.host == null) {
3739
throw new Error("Sentinel client needs a host and port");
@@ -42,13 +44,30 @@ function RedisSentinelClient(options) {
4244
throw new Error("Sentinel client takes only options to initialize");
4345
}
4446

45-
// this client will always be connected to the active master.
46-
// exposed publicly.
47-
// (initialized on reconnect())
48-
this.activeMasterClient = null;
47+
// this client will always be connected to the active master
48+
self.debug("Creating new dummy master");
49+
// Make new client
50+
self.activeMasterClient = new RedisSingleClient.createClient( 9999, '127.0.0.1',
51+
{
52+
sentinel: false,
53+
disable_flush: true // Disables flush_and_error, to preserve queue
54+
}
55+
);
4956

50-
// used for swaps
51-
this.oldMasterClient = null;
57+
// pass up errors
58+
// @todo emit a separate 'master error' event?
59+
self.activeMasterClient.on('error', function(error){
60+
if (self.emitMasterErrors) {
61+
error.message = self.myName + " master error: " + error.message;
62+
self.onError.call(self, error);
63+
}
64+
});
65+
66+
// pass up messages
67+
self.activeMasterClient.on('message', function(channel, message){
68+
self.emit('message', channel, message);
69+
});
70+
5271

5372
// used for logging & errors
5473
this.myName = 'sentinel-' + this.options.host + ':' + this.options.port + '-' + this.options.masterName;
@@ -125,6 +144,12 @@ function RedisSentinelClient(options) {
125144
self.emit('sentinel message', msg);
126145

127146
switch(msg) {
147+
case '+sdown':
148+
self.debug('Down detected');
149+
self.emit('down-start');
150+
self.emitMasterErrors = false;
151+
break;
152+
128153
case '+failover-triggered':
129154
self.debug('Failover detected');
130155
self.emit('failover-start');
@@ -178,52 +203,26 @@ RedisSentinelClient.prototype.reconnect = function reconnect(onReconnectCallback
178203
return;
179204
}
180205

206+
181207
self.debug("Changing master from " +
182208
(self.activeMasterClient ? self.activeMasterClient.host + ":" + self.activeMasterClient.port : "[none]") +
183209
" to " + newMaster.host + ":" + newMaster.port);
184210

185-
// "Note that this does not wait until all replies have been parsed.
186-
// If you want to exit cleanly, call client.quit()"
187-
// @review
188-
189-
// we don't want to queue commands. so push aside the old one, kill it on the side,
190-
// and simultaneously swap in a new one.
191-
// @review does this work?
192-
self.oldMasterClient = self.activeMasterClient;
211+
// reconfigure it
212+
self.activeMasterClient.host = newMaster.host;
213+
self.activeMasterClient.port = newMaster.port;
193214

194-
// note, old client will be null on 1st connect
195-
if (self.oldMasterClient) {
196-
self.debug('old master was on ' + self.oldMasterClient.host + ':' + self.oldMasterClient.port);
197-
198-
// @check if this fn ends before end is called, will event still fire?
199-
self.oldMasterClient.once('end', function(){
200-
self.debug("Old master ended");
201-
self.emit('disconnected');
202-
});
203-
}
215+
// reconnect it
216+
self.activeMasterClient.forceReconnectionAttempt();
204217

205-
// new master client
206-
// should queue all subsequent commands internally.
207-
// but any commands still queued in the old master, will be lost.
208-
self.activeMasterClient = new RedisSingleClient.createClient(newMaster.port, newMaster.host, { sentinel: false });
209218

210-
// kill the old one
211-
if (self.oldMasterClient) {
212-
self.oldMasterClient.end();
213-
}
214-
215-
// pass up errors, (& other events?)
216-
// @todo emit a separate 'master error' event?
217-
self.activeMasterClient.on('error', function(error){
218-
error.message = self.myName + " master error: " + error.message;
219-
self.onError.call(self, error);
220-
});
221219

222220
// @todo use no_ready_check = true? then change this 'ready' to 'connect'
223221

224222
// backwards-compat. w/RedisClient
225223
self.activeMasterClient.once('connect', function(){
226224
self.emit('connect');
225+
self.emitMasterErrors = true;
227226
});
228227

229228
self.activeMasterClient.once('ready', function(){

0 commit comments

Comments
 (0)