mranney/node_redis — pull request #139 by felixge (2011-10-17 09:09:00+00:00)
Title: Fix: Hiredis parser traps pubsub event exceptions 

While using this module with the hiredis parser, I noticed that exceptions
thrown inside of subscribe/message/etc. callbacks would be reported as
parser error exceptions, which was confusing.

Example:

```
var client = require('./index').createClient();

client.on('subscribe', function() {
throw new Error('My Error');
});
client.subscribe('channel');
```
I would expect the above to throw 'My Error' as a simple exception, however,
when using the hiredis parser I get:

```
events.js:45
throw arguments[1]; // Unhandled 'error' event
^
Error: Redis reply parser error: Error: My Error
at RedisClient. (/Users/felix/code/node_redis/hiredis.js:4:9)
at RedisClient.emit (events.js:67:17)
at RedisClient.return_reply (/Users/felix/code/node_redis/index.js:457:22)
at HiredisReplyParser. (/Users/felix/code/node_redis/index.js:220:14)
at HiredisReplyParser.emit (events.js:64:17)
at HiredisReplyParser.execute (/Users/felix/code/node_redis/lib/parser/hiredis.js:35:22)
at RedisClient.on_data (/Users/felix/code/node_redis/index.js:365:27)
at Socket. (/Users/felix/code/node_redis/index.js:58:14)
...
```

The attached patch fixes this problem by changing the way the HiredisReplyParser
traps exceptions, and also provides a unit test for it.

Please let me know if you need any tweaks on the patch for landing it, I was
not quite sure where to put my test / how to structure it, since most test
cases seem to be integration tests at this point.

Also, if you would prefer an integration test for this, here you go:

``` javascript
var client = require('./index').createClient();
var assert = require('assert');

process.on('uncaughtException', function listener(err) {
process.removeListener('uncaughtException', listener);

// Drop the stack, otherwise the assert gets trapped by node
process.nextTick(function() {
assert.ok(!/parser error/.test(err.message), err.message);
client.quit();
});
});

client.on('subscribe', function() {
throw new Error('My Error');
});
client.subscribe('channel');
```

PS: If you wonder why this only affects pubsub events: This is because
RedisClient#return_reply does exception trapping differently for events than
it does for callbacks.

See: https://github.com/mranney/node_redis/blob/3e95c55a0301104c9cd6451d71fa5527b7797792/index.js#L431
Vs: https://github.com/mranney/node_redis/blob/3e95c55a0301104c9cd6451d71fa5527b7797792/index.js#L447