1
0
mirror of https://github.com/redis/node-redis.git synced 2025-08-06 02:15:48 +03:00

Emit errors instead of throwing them

Thrown errors might kill the users app. By emitting the errors the user is able to catch all errors in one place without the app going down
This commit is contained in:
Ruben Bridgewater
2015-09-07 14:54:08 +02:00
parent c6ae7832a3
commit 4f0443cdd4
6 changed files with 43 additions and 45 deletions

View File

@@ -280,6 +280,8 @@ RedisClient.prototype.init_parser = function () {
return true; return true;
} }
})) { })) {
// Do not emit this error
// This should take down the app if anyone made such a huge mistake or should somehow be handled in user code
throw new Error("Couldn't find named parser " + self.options.parser + " on this system"); throw new Error("Couldn't find named parser " + self.options.parser + " on this system");
} }
} else { } else {
@@ -629,10 +631,12 @@ RedisClient.prototype.return_reply = function (reply) {
} }
this.emit(type, reply1String, reply[2]); // channel, count this.emit(type, reply1String, reply[2]); // channel, count
} else { } else {
throw new Error("subscriptions are active but got unknown reply type " + type); this.emit("error", new Error("subscriptions are active but got unknown reply type " + type));
return;
} }
} else if (! this.closing) { } else if (!this.closing) {
throw new Error("subscriptions are active but got an invalid reply: " + reply); this.emit("error", new Error("subscriptions are active but got an invalid reply: " + reply));
return;
} }
} else if (this.monitoring) { } else if (this.monitoring) {
len = reply.indexOf(" "); len = reply.indexOf(" ");
@@ -643,7 +647,7 @@ RedisClient.prototype.return_reply = function (reply) {
}); });
this.emit("monitor", timestamp, args); this.emit("monitor", timestamp, args);
} else { } else {
throw new Error("node_redis command queue state error. If you can reproduce this, please report it."); this.emit("error", new Error("node_redis command queue state error. If you can reproduce this, please report it."));
} }
}; };
@@ -702,9 +706,16 @@ RedisClient.prototype.send_command = function (command, args, callback) {
// if the value is undefined or null and command is set or setx, need not to send message to redis // if the value is undefined or null and command is set or setx, need not to send message to redis
if (command === 'set' || command === 'setex') { if (command === 'set' || command === 'setex') {
if(args[args.length - 1] === undefined || args[args.length - 1] === null) { if (args.length === 0) {
return;
}
if (args[args.length - 1] === undefined || args[args.length - 1] === null) {
var err = new Error('send_command: ' + command + ' value must not be undefined or null'); var err = new Error('send_command: ' + command + ' value must not be undefined or null');
return callback && callback(err); if (callback) {
return callback && callback(err);
}
this.emit("error", err);
return;
} }
} }
@@ -731,7 +742,8 @@ RedisClient.prototype.send_command = function (command, args, callback) {
if (command_obj.callback) { if (command_obj.callback) {
command_obj.callback(not_writeable_error); command_obj.callback(not_writeable_error);
} else { } else {
throw not_writeable_error; this.emit("error", not_writeable_error);
return;
} }
} }
@@ -745,7 +757,8 @@ RedisClient.prototype.send_command = function (command, args, callback) {
} else if (command === "quit") { } else if (command === "quit") {
this.closing = true; this.closing = true;
} else if (this.pub_sub_mode === true) { } else if (this.pub_sub_mode === true) {
throw new Error("Connection in subscriber mode, only subscriber commands may be used"); this.emit("error", new Error("Connection in subscriber mode, only subscriber commands may be used"));
return;
} }
this.command_queue.push(command_obj); this.command_queue.push(command_obj);
this.commands_sent += 1; this.commands_sent += 1;
@@ -1032,7 +1045,7 @@ Multi.prototype.exec = function (callback) {
callback(errors); callback(errors);
return; return;
} else { } else {
throw new Error(err); self._client.emit('error', err);
} }
} }

View File

@@ -114,7 +114,7 @@ describe("The 'eval' method", function () {
client.evalsha(sha, 0, helper.isString('eval get sha test', done)); client.evalsha(sha, 0, helper.isString('eval get sha test', done));
}); });
it('throws an error if SHA does not exist', function (done) { it('returns an error if SHA does not exist', function (done) {
helper.serverVersionAtLeast.call(this, client, [2, 5, 0]); helper.serverVersionAtLeast.call(this, client, [2, 5, 0]);
client.evalsha('ffffffffffffffffffffffffffffffffffffffff', 0, helper.isError(done)); client.evalsha('ffffffffffffffffffffffffffffffffffffffff', 0, helper.isError(done));
}); });

View File

@@ -92,13 +92,10 @@ describe("The 'mset' method", function () {
describe("with undefined 'key' and missing 'value' parameter", function () { describe("with undefined 'key' and missing 'value' parameter", function () {
// this behavior is different from the 'set' behavior. // this behavior is different from the 'set' behavior.
it("throws an error", function (done) { it("emits an error", function (done) {
var mochaListener = helper.removeMochaListener(); client.on('error', function (err) {
assert.equal(err.message, "ERR wrong number of arguments for 'mset' command");
process.once('uncaughtException', function (err) { done();
process.on('uncaughtException', mochaListener);
helper.isError()(err, null);
return done();
}); });
client.mset(); client.mset();

View File

@@ -24,7 +24,7 @@ describe("The 'select' method", function () {
}); });
}); });
it("throws an error if redis is not connected", function (done) { it("returns an error if redis is not connected", function (done) {
client.select(1, function (err, res) { client.select(1, function (err, res) {
assert(err.message.match(/Redis connection gone/)); assert(err.message.match(/Redis connection gone/));
done(); done();
@@ -67,7 +67,7 @@ describe("The 'select' method", function () {
}); });
describe("with an invalid db index", function () { describe("with an invalid db index", function () {
it("emits an error", function (done) { it("returns an error", function (done) {
assert.strictEqual(client.selected_db, null, "default db should be null"); assert.strictEqual(client.selected_db, null, "default db should be null");
client.select(9999, function (err) { client.select(9999, function (err) {
assert.equal(err.message, 'ERR invalid DB index'); assert.equal(err.message, 'ERR invalid DB index');
@@ -90,14 +90,12 @@ describe("The 'select' method", function () {
}); });
describe("with an invalid db index", function () { describe("with an invalid db index", function () {
it("throws an error when callback not provided", function (done) { it("emits an error when callback not provided", function (done) {
var mochaListener = helper.removeMochaListener();
assert.strictEqual(client.selected_db, null, "default db should be null"); assert.strictEqual(client.selected_db, null, "default db should be null");
process.once('uncaughtException', function (err) { client.on('error', function (err) {
process.on('uncaughtException', mochaListener);
assert.equal(err.message, 'ERR invalid DB index'); assert.equal(err.message, 'ERR invalid DB index');
return done(); done();
}); });
client.select(9999); client.select(9999);

View File

@@ -96,8 +96,7 @@ describe("The 'set' method", function () {
this.timeout(200); this.timeout(200);
client.once("error", function (err) { client.once("error", function (err) {
helper.isError()(err, null); done(err);
return done(err);
}); });
client.set(); client.set();
@@ -107,20 +106,13 @@ describe("The 'set' method", function () {
}, 100); }, 100);
}); });
it("does not throw an error", function (done) { it("does emit an error", function (done) {
this.timeout(200); client.on('error', function (err) {
var mochaListener = helper.removeMochaListener(); assert.equal(err.message, "ERR wrong number of arguments for 'set' command");
done();
process.once('uncaughtException', function (err) {
process.on('uncaughtException', mochaListener);
return done(err);
}); });
client.set(); client.set('foo');
setTimeout(function () {
done();
}, 100);
}); });
}); });
}); });

View File

@@ -647,7 +647,7 @@ describe("The node_redis client", function () {
describe('enable_offline_queue', function () { describe('enable_offline_queue', function () {
describe('true', function () { describe('true', function () {
it("does not throw an error and enqueues operation", function (done) { it("does not return an error and enqueues operation", function (done) {
var client = redis.createClient(9999, null, { var client = redis.createClient(9999, null, {
max_attempts: 1, max_attempts: 1,
parser: parser parser: parser
@@ -674,20 +674,18 @@ describe("The node_redis client", function () {
}); });
describe('false', function () { describe('false', function () {
it("does not throw an error and enqueues operation", function (done) { it("does not emit an error and enqueues operation", function (done) {
var client = redis.createClient(9999, null, { var client = redis.createClient(9999, null, {
parser: parser, parser: parser,
max_attempts: 1, max_attempts: 1,
enable_offline_queue: false enable_offline_queue: false
}); });
client.on('error', function() { client.on('error', function(err) {
// ignore, b/c expecting a "can't connect" error assert(/send_command: stream not writeable|ECONNREFUSED/.test(err.message));
}); });
assert.throws(function () { client.set('foo', 'bar');
client.set('foo', 'bar');
});
assert.doesNotThrow(function () { assert.doesNotThrow(function () {
client.set('foo', 'bar', function (err) { client.set('foo', 'bar', function (err) {