Skip to content

Commit

Permalink
fix: reconnect when getting fatal error (#292)
Browse files Browse the repository at this point in the history
* fix: reconnect when getting fatal error

* test: add test for Redis#flushQueue

* test: add test for fatal error
  • Loading branch information
luin committed May 2, 2016
1 parent 02eb721 commit 1cf2ac1
Show file tree
Hide file tree
Showing 4 changed files with 74 additions and 9 deletions.
24 changes: 17 additions & 7 deletions lib/redis.js
Original file line number Diff line number Diff line change
Expand Up @@ -353,18 +353,28 @@ Redis.prototype.duplicate = function (override) {
* Flush offline queue and command queue with error.
*
* @param {Error} error - The error object to send to the commands
* @param {object} options
* @private
*/
Redis.prototype.flushQueue = function (error) {
Redis.prototype.flushQueue = function (error, options) {
options = _.defaults({}, options, {
offlineQueue: true,
commandQueue: true
});

var item;
while (this.offlineQueue.length > 0) {
item = this.offlineQueue.shift();
item.command.reject(error);
if (options.offlineQueue) {
while (this.offlineQueue.length > 0) {
item = this.offlineQueue.shift();
item.command.reject(error);
}
}

while (this.commandQueue.length > 0) {
item = this.commandQueue.shift();
item.command.reject(error);
if (options.commandQueue) {
while (this.commandQueue.length > 0) {
item = this.commandQueue.shift();
item.command.reject(error);
}
}
};

Expand Down
4 changes: 3 additions & 1 deletion lib/redis/parser.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,9 @@ exports.initParser = function () {
_this.returnReply(reply);
},
returnFatalError: function (err) {
_this.emit('error', new Error('Redis reply parser error: ' + err.stack));
_this.flushQueue(err, { offlineQueue: false });
_this.silentEmit('error', new Error('Redis parser fatal error: ' + err.stack));
_this.disconnect(true);
}
});
};
Expand Down
21 changes: 21 additions & 0 deletions test/functional/fatal_error.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
'use strict';

describe('fatal_error', function () {
it('should handle fatal error of parser', function (done) {
var redis = new Redis();
redis.once('ready', function () {
var execute = redis.replyParser.execute;
redis.replyParser.execute = function () {
execute.call(redis.replyParser, '&');
};
redis.get('foo', function (err) {
expect(err.message).to.match(/Protocol error/);
redis.replyParser.execute = execute;
redis.get('bar', function (err) {
expect(err).to.eql(null);
done();
});
});
});
});
});
34 changes: 33 additions & 1 deletion test/unit/redis.js
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ describe('Redis', function () {
}
Redis.prototype.connect.restore();

function getOption () {
function getOption() {
var redis = Redis.apply(null, arguments);
return redis.options;
}
Expand Down Expand Up @@ -115,4 +115,36 @@ describe('Redis', function () {
redis.end();
});
});

describe('#flushQueue', function () {
it('should flush all queues by default', function () {
var flushQueue = Redis.prototype.flushQueue;
var redis = {
offlineQueue: [{ command: { reject: function () {} } }],
commandQueue: [{ command: { reject: function () {} } }]
};
var offline = mock(redis.offlineQueue[0].command);
var command = mock(redis.commandQueue[0].command);
offline.expects('reject').once();
command.expects('reject').once();
flushQueue.call(redis);
offline.verify();
command.verify();
});

it('should be able to ignore a queue', function () {
var flushQueue = Redis.prototype.flushQueue;
var redis = {
offlineQueue: [{ command: { reject: function () {} } }],
commandQueue: [{ command: { reject: function () {} } }]
};
var offline = mock(redis.offlineQueue[0].command);
var command = mock(redis.commandQueue[0].command);
offline.expects('reject').once();
command.expects('reject').never();
flushQueue.call(redis, new Error(), { commandQueue: false });
offline.verify();
command.verify();
});
});
});

0 comments on commit 1cf2ac1

Please sign in to comment.