Skip to content

Commit 6a5e011

Browse files
committed
Merge pull request #858 from fintura/codes
Add redis error codes to the errors returned by the parser. Fixes #538
2 parents 7e68925 + 959b0ee commit 6a5e011

File tree

5 files changed

+33
-6
lines changed

5 files changed

+33
-6
lines changed

index.js

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -500,12 +500,19 @@ RedisClient.prototype.connection_gone = function (why) {
500500
this.retry_timer = setTimeout(retry_connection, this.retry_delay, this);
501501
};
502502

503+
var err_code = /^([A-Z]+)\s+(.+)$/;
503504
RedisClient.prototype.return_error = function (err) {
504505
var command_obj = this.command_queue.shift(), queue_len = this.command_queue.length;
505506
if (command_obj.command && command_obj.command.toUpperCase) {
506507
err.command_used = command_obj.command.toUpperCase();
507508
}
508509

510+
var match = err.message.match(err_code);
511+
// LUA script could return user errors that don't behave like all other errors!
512+
if (match) {
513+
err.code = match[1];
514+
}
515+
509516
if (this.pub_sub_mode === false && queue_len === 0) {
510517
this.command_queue = new Queue();
511518
this.emit("idle");
@@ -1053,7 +1060,6 @@ Multi.prototype.execute_callback = function (err, replies) {
10531060

10541061
if (err) {
10551062
if (err.code !== 'CONNECTION_BROKEN') {
1056-
err.code = 'EXECABORT';
10571063
err.errors = this.errors;
10581064
if (this.callback) {
10591065
this.callback(err);
@@ -1071,7 +1077,13 @@ Multi.prototype.execute_callback = function (err, replies) {
10711077
args = this.queue[i];
10721078

10731079
// If we asked for strings, even in detect_buffers mode, then return strings:
1074-
if (reply) {
1080+
if (reply instanceof Error) {
1081+
var match = reply.message.match(err_code);
1082+
// LUA script could return user errors that don't behave like all other errors!
1083+
if (match) {
1084+
reply.code = match[1];
1085+
}
1086+
} else if (reply) {
10751087
if (this._client.options.detect_buffers && this.wants_buffers[i] === false) {
10761088
replies[i - 1] = reply = reply_to_strings(reply);
10771089
}

test/commands/eval.spec.js

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,11 @@ describe("The 'eval' method", function () {
5252

5353
it('converts lua error to an error response', function (done) {
5454
helper.serverVersionAtLeast.call(this, client, [2, 5, 0]);
55-
client.eval("return {err='this is an error'}", 0, helper.isError(done));
55+
client.eval("return {err='this is an error'}", 0, function(err) {
56+
assert(err.code === undefined);
57+
helper.isError()(err);
58+
done();
59+
});
5660
});
5761

5862
it('represents a lua table appropritely', function (done) {
@@ -124,6 +128,7 @@ describe("The 'eval' method", function () {
124128
helper.serverVersionAtLeast.call(this, client, [2, 5, 0]);
125129
client.evalsha('ffffffffffffffffffffffffffffffffffffffff', 0);
126130
client.on('error', function(err) {
131+
assert.equal(err.code, 'NOSCRIPT');
127132
assert(/NOSCRIPT No matching script. Please use EVAL./.test(err.message));
128133
done();
129134
});

test/commands/keys.spec.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@ describe("The 'keys' method", function () {
1414
var client;
1515

1616
beforeEach(function (done) {
17+
args = args || {};
18+
// This is going to test if the high water is also respected
19+
args.command_queue_high_water = 100;
1720
client = redis.createClient.apply(redis.createClient, args);
1821
client.once("connect", function () {
1922
client.flushdb(done);

test/commands/multi.spec.js

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -254,15 +254,19 @@ describe("The 'multi' method", function () {
254254
assert(err.message.match(/^EXECABORT/), "Error message should begin with EXECABORT");
255255
assert.equal(err.errors.length, 2, "err.errors should have 2 items");
256256
assert.strictEqual(err.errors[0].command_used, 'SET');
257+
assert.strictEqual(err.errors[0].code, 'ERR');
257258
assert.strictEqual(err.errors[0].position, 1);
258259
assert(/^ERR/.test(err.errors[0].message), "Actuall error message should begin with ERR");
259260
return done();
260261
});
261262
});
262263

263264
it('reports multiple exceptions when they occur (while EXEC is running)', function (done) {
264-
client.multi().config("bar").debug("foo").exec(function (err, reply) {
265-
assert.strictEqual(reply.length, 2);
265+
client.multi().config("bar").debug("foo").eval("return {err='this is an error'}", 0).exec(function (err, reply) {
266+
assert.strictEqual(reply.length, 3);
267+
assert.equal(reply[0].code, 'ERR');
268+
assert.equal(reply[2].code, undefined);
269+
assert(/^this is an error/.test(reply[2].message));
266270
assert(/^ERR/.test(reply[0].message), "Error message should begin with ERR");
267271
assert(/^ERR/.test(reply[1].message), "Error message should begin with ERR");
268272
return done();
@@ -275,6 +279,7 @@ describe("The 'multi' method", function () {
275279
multi.set('foo', 'bar', helper.isString('OK'));
276280
multi.debug("foo").exec(function (err, reply) {
277281
assert.strictEqual(reply.length, 3);
282+
assert.strictEqual(reply[0].code, 'ERR');
278283
assert(/^ERR/.test(reply[0].message), "Error message should begin with ERR");
279284
assert(/^ERR/.test(reply[2].message), "Error message should begin with ERR");
280285
assert.strictEqual(reply[1], "OK");

test/commands/select.spec.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,8 @@ describe("The 'select' method", function () {
5757
describe("with a valid db index", function () {
5858
it("selects the appropriate database", function (done) {
5959
assert.strictEqual(client.selected_db, null, "default db should be null");
60-
client.select(1, function () {
60+
client.select(1, function (err) {
61+
assert.equal(err, null);
6162
assert.equal(client.selected_db, 1, "we should have selected the new valid DB");
6263
return done();
6364
});
@@ -68,6 +69,7 @@ describe("The 'select' method", function () {
6869
it("returns an error", function (done) {
6970
assert.strictEqual(client.selected_db, null, "default db should be null");
7071
client.select(9999, function (err) {
72+
assert.equal(err.code, 'ERR');
7173
assert.equal(err.message, 'ERR invalid DB index');
7274
return done();
7375
});

0 commit comments

Comments
 (0)