Skip to content

Commit 1cf2ac1

Browse files
committed
fix: reconnect when getting fatal error (#292)
* fix: reconnect when getting fatal error * test: add test for Redis#flushQueue * test: add test for fatal error
1 parent 02eb721 commit 1cf2ac1

File tree

4 files changed

+74
-9
lines changed

4 files changed

+74
-9
lines changed

lib/redis.js

+17-7
Original file line numberDiff line numberDiff line change
@@ -353,18 +353,28 @@ Redis.prototype.duplicate = function (override) {
353353
* Flush offline queue and command queue with error.
354354
*
355355
* @param {Error} error - The error object to send to the commands
356+
* @param {object} options
356357
* @private
357358
*/
358-
Redis.prototype.flushQueue = function (error) {
359+
Redis.prototype.flushQueue = function (error, options) {
360+
options = _.defaults({}, options, {
361+
offlineQueue: true,
362+
commandQueue: true
363+
});
364+
359365
var item;
360-
while (this.offlineQueue.length > 0) {
361-
item = this.offlineQueue.shift();
362-
item.command.reject(error);
366+
if (options.offlineQueue) {
367+
while (this.offlineQueue.length > 0) {
368+
item = this.offlineQueue.shift();
369+
item.command.reject(error);
370+
}
363371
}
364372

365-
while (this.commandQueue.length > 0) {
366-
item = this.commandQueue.shift();
367-
item.command.reject(error);
373+
if (options.commandQueue) {
374+
while (this.commandQueue.length > 0) {
375+
item = this.commandQueue.shift();
376+
item.command.reject(error);
377+
}
368378
}
369379
};
370380

lib/redis/parser.js

+3-1
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,9 @@ exports.initParser = function () {
2828
_this.returnReply(reply);
2929
},
3030
returnFatalError: function (err) {
31-
_this.emit('error', new Error('Redis reply parser error: ' + err.stack));
31+
_this.flushQueue(err, { offlineQueue: false });
32+
_this.silentEmit('error', new Error('Redis parser fatal error: ' + err.stack));
33+
_this.disconnect(true);
3234
}
3335
});
3436
};

test/functional/fatal_error.js

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
'use strict';
2+
3+
describe('fatal_error', function () {
4+
it('should handle fatal error of parser', function (done) {
5+
var redis = new Redis();
6+
redis.once('ready', function () {
7+
var execute = redis.replyParser.execute;
8+
redis.replyParser.execute = function () {
9+
execute.call(redis.replyParser, '&');
10+
};
11+
redis.get('foo', function (err) {
12+
expect(err.message).to.match(/Protocol error/);
13+
redis.replyParser.execute = execute;
14+
redis.get('bar', function (err) {
15+
expect(err).to.eql(null);
16+
done();
17+
});
18+
});
19+
});
20+
});
21+
});

test/unit/redis.js

+33-1
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ describe('Redis', function () {
8484
}
8585
Redis.prototype.connect.restore();
8686

87-
function getOption () {
87+
function getOption() {
8888
var redis = Redis.apply(null, arguments);
8989
return redis.options;
9090
}
@@ -115,4 +115,36 @@ describe('Redis', function () {
115115
redis.end();
116116
});
117117
});
118+
119+
describe('#flushQueue', function () {
120+
it('should flush all queues by default', function () {
121+
var flushQueue = Redis.prototype.flushQueue;
122+
var redis = {
123+
offlineQueue: [{ command: { reject: function () {} } }],
124+
commandQueue: [{ command: { reject: function () {} } }]
125+
};
126+
var offline = mock(redis.offlineQueue[0].command);
127+
var command = mock(redis.commandQueue[0].command);
128+
offline.expects('reject').once();
129+
command.expects('reject').once();
130+
flushQueue.call(redis);
131+
offline.verify();
132+
command.verify();
133+
});
134+
135+
it('should be able to ignore a queue', function () {
136+
var flushQueue = Redis.prototype.flushQueue;
137+
var redis = {
138+
offlineQueue: [{ command: { reject: function () {} } }],
139+
commandQueue: [{ command: { reject: function () {} } }]
140+
};
141+
var offline = mock(redis.offlineQueue[0].command);
142+
var command = mock(redis.commandQueue[0].command);
143+
offline.expects('reject').once();
144+
command.expects('reject').never();
145+
flushQueue.call(redis, new Error(), { commandQueue: false });
146+
offline.verify();
147+
command.verify();
148+
});
149+
});
118150
});

0 commit comments

Comments
 (0)