Socket
Socket
Sign inDemoInstall

ioredis

Package Overview
Dependencies
Maintainers
1
Versions
228
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

ioredis - npm Package Compare versions

Comparing version 1.0.10 to 1.0.11

test/functional/show_friendly_error_stack.js

18

lib/command.js

@@ -36,10 +36,19 @@ var _ = require('lodash');

*/
function Command(name, args, replyEncoding, callback) {
function Command(name, args, options, callback) {
this.name = name;
this.replyEncoding = options && options.replyEncoding;
this.errorStack = options && options.errorStack;
this.args = args ? _.flatten(args) : [];
var _this = this;
this.promise = new Promise(function (resolve, reject) {
_this.resolve = _this._convertValue(resolve);
_this.reject = reject;
if (_this.errorStack) {
_this.reject = function (err) {
reject(utils.optimizeErrorStack(err, _this.errorStack, __dirname));
};
} else {
_this.reject = reject;
}
_this.name = name;
_this.args = args ? _.flatten(args) : [];
var transformer = Command._transformer.argument[_this.name];

@@ -49,3 +58,2 @@ if (transformer) {

}
_this.replyEncoding = replyEncoding;
}).nodeify(callback);

@@ -52,0 +60,0 @@ }

var _ = require('lodash');
var Command = require('./command');
function Commander () {}
function Commander() {
this.options = _.defaults(this.options || {}, {
showFriendlyErrorStack: false
});
}

@@ -19,3 +23,10 @@ var commands = _.difference(_.keys(require('ioredis-commands'), ['monitor']));

return this.sendCommand(new Command(commandName, args, 'utf8', callback));
var options = { replyEncoding: 'utf8' };
if (this.options.showFriendlyErrorStack) {
options.errorStack = new Error().stack;
}
var command = new Command(commandName, args, options, callback);
return this.sendCommand(command);
};

@@ -31,3 +42,9 @@

return this.sendCommand(new Command(commandName, args, null, callback));
var options = { replyEncoding: null };
if (this.options.showFriendlyErrorStack) {
options.errorStack = new Error().stack;
}
var command = new Command(commandName, args, options, callback);
return this.sendCommand(command);
};

@@ -45,3 +62,9 @@ });

return this.sendCommand(new Command(commandName, args, 'utf8', callback));
var options = { replyEncoding: 'utf8' };
if (this.options && this.options.showFriendlyErrorStack) {
options.errorStack = new Error().stack;
}
var command = new Command(commandName, args, options, callback);
return this.sendCommand(command);
};

@@ -58,3 +81,9 @@

return this.sendCommand(new Command(commandName, args, null, callback));
var options = { replyEncoding: null };
if (this.options && this.options.showFriendlyErrorStack) {
options.errorStack = new Error().stack;
}
var command = new Command(commandName, args, options, callback);
return this.sendCommand(command);
};

@@ -61,0 +90,0 @@

@@ -7,2 +7,4 @@ var _ = require('lodash');

function Pipeline(redis) {
Commander.call(this);
this.redis = redis;

@@ -82,6 +84,5 @@ this._queue = [];

if (scripts.length) {
var checkExists = new Command('script', ['exists'].concat(scripts.map(function (item) {
promise = this.redis.script('exists', scripts.map(function (item) {
return item.sha;
})), 'utf8');
promise = this.redis.sendCommand(checkExists).then(function (results) {
})).then(function (results) {
var pending = [];

@@ -94,3 +95,3 @@ for (var i = 0; i < results.length; ++i) {

return Promise.all(pending.map(function (script) {
return _this.redis.sendCommand(new Command('script', ['load', script.lua], 'utf8'));
return _this.redis.script('load', script.lua);
}));

@@ -97,0 +98,0 @@ });

@@ -32,3 +32,3 @@ var Redis = require('./redis');

this.fails = 0;
this.options = _.defaults(options || {}, RedisCluster._defaultOptions);
this.options = _.defaults(options || {}, this.options || {}, RedisCluster._defaultOptions);

@@ -35,0 +35,0 @@ this.startupNodes = startupNodes.map(function (options) {

@@ -89,5 +89,6 @@ var _ = require('lodash');

var resultOptions;
if (typeof port === 'object') {
// Redis(options)
this.options = _.cloneDeep(port);
resultOptions = port;
} else if (typeof port === 'string' && !utils.isInt(port)) {

@@ -109,17 +110,17 @@ // Redis(url, options)

}
this.options = _.defaults(host ? _.cloneDeep(host) : {}, parsedOptions);
resultOptions = _.defaults(host || {}, parsedOptions);
} else {
// Redis(port, host, options) or Redis(port, options)
if (host && typeof host === 'object') {
this.options = _.defaults(_.cloneDeep(host), { port: port });
resultOptions = _.defaults(host, { port: port });
} else {
this.options = _.defaults(options ? _.cloneDeep(options) : {}, { port: port, host: host });
resultOptions = _.defaults(options || {}, { port: port, host: host });
}
}
_.defaults(this.options, Redis._defaultOptions);
if (typeof this.options.port === 'string') {
this.options.port = parseInt(this.options.port, 10);
if (resultOptions && typeof resultOptions.port === 'string') {
resultOptions.port = parseInt(resultOptions.port, 10);
}
this.options = _.defaults(resultOptions || {}, this.options || {}, Redis._defaultOptions);
if (this.options.parser === 'javascript') {

@@ -329,3 +330,3 @@ this.Parser = require('./parsers/javascript');

var _this = this;
this.sendCommand(new Command('info', null, 'utf8', function (err, res) {
this.info(function (err, res) {
if (err) {

@@ -357,3 +358,3 @@ return callback(err);

}
}));
});
};

@@ -387,3 +388,8 @@

return script.execute(this, args, 'utf8', callback);
var options = { replyEncoding: 'utf8' };
if (this.options.showFriendlyErrorStack) {
options.errorStack = new Error().stack;
}
return script.execute(this, args, options, callback);
};

@@ -399,3 +405,8 @@

return script.execute(this, args, null, callback);
var options = { replyEncoding: null };
if (this.options.showFriendlyErrorStack) {
options.errorStack = new Error().stack;
}
return script.execute(this, args, options, callback);
};

@@ -614,2 +625,4 @@ };

Redis.Promise = Promise;
var Sentinel = require('./sentinel');

@@ -15,3 +15,3 @@ var Queue = require('fastqueue');

if (self.condition.auth) {
self.sendCommand(new Command('auth', [self.condition.auth], 'utf8', function (err, res) {
self.auth(self.condition.auth, function (err, res) {
if (res === 'OK') {

@@ -27,3 +27,3 @@ return;

}
}));
});
}

@@ -101,11 +101,3 @@

return function (data) {
try {
self.replyParser.execute(data);
} catch (error) {
// This is an unexpected parser problem, an exception that came from the parser code itself.
// Parser should emit "error" events if it notices things are out of whack.
// Callbacks that throw exceptions will land in return_reply(), below.
// TODO - it might be nice to have a different "error" event for different types of errors
self.silentEmit('error', error);
}
self.replyParser.execute(data);
};

@@ -136,3 +128,3 @@ };

if (item.select !== self.condition.select && item.command.name !== 'select') {
self.sendCommand(new Command('select', [item.select]));
self.select(item.select);
}

@@ -146,3 +138,3 @@ self.sendCommand(item.command, item.stream);

debug('connect to db [%d]', finalSelect);
self.sendCommand(new Command('select', [finalSelect]));
self.selectBuffer(finalSelect);
}

@@ -153,3 +145,3 @@

if (condition.mode.monitoring) {
self.sendCommand(new Command('monitor', null, 'utf8', function () {
self.call('monitor', function () {
self.sendCommand = function (command) {

@@ -160,3 +152,3 @@ command.reject(new Error('Connection is in monitoring mode, can\'t process commands.'));

self.emit('monitoring');
}));
});
} else {

@@ -163,0 +155,0 @@ if (condition.mode.subscriber && self.options.autoResubscribe) {

@@ -41,2 +41,7 @@ var _ = require('lodash');

err.command = {
name: command.name,
args: command.args
};
command.reject(err);

@@ -43,0 +48,0 @@ };

@@ -11,3 +11,3 @@ var Command = require('./command');

Script.prototype.execute = function (container, args, replyEncoding, callback) {
Script.prototype.execute = function (container, args, options, callback) {
if (this.numberOfKeys) {

@@ -17,3 +17,3 @@ args.unshift(this.numberOfKeys);

var result = container.sendCommand(new Command('evalsha', [this.sha].concat(args), replyEncoding));
var result = container.sendCommand(new Command('evalsha', [this.sha].concat(args), options));
if (result instanceof Promise) {

@@ -25,3 +25,3 @@ var _this = this;

}
return container.sendCommand(new Command('eval', [_this.lua].concat(args), replyEncoding));
return container.sendCommand(new Command('eval', [_this.lua].concat(args), options));
}).nodeify(callback);

@@ -28,0 +28,0 @@ }

@@ -224,1 +224,25 @@ /**

};
/**
* Optimize error stack
*
* @param {Error} error - actually error
* @param {string} friendlyStack - the stack that more meaningful
* @param {string} filterPath - only show stacks with the specified path
*/
exports.optimizeErrorStack = function (error, friendlyStack, filterPath) {
var stacks = friendlyStack.split('\n');
var lines = '';
var i;
for (i = 1; i < stacks.length; ++i) {
if (stacks[i].indexOf(filterPath) === -1) {
break;
}
}
for (var j = i; j < stacks.length; ++j) {
lines += '\n' + stacks[j];
}
var pos = error.stack.indexOf('\n');
error.stack = error.stack.slice(0, pos) + lines;
return error;
};
{
"name": "ioredis",
"version": "1.0.10",
"version": "1.0.11",
"description": "A delightful, performance-focused Redis client for Node and io.js",

@@ -5,0 +5,0 @@ "main": "index.js",

@@ -10,3 +10,3 @@ # ioredis

Support Redis >= 2.6.12 and (Node.js >= 0.11.13 or io.js).
Support Redis >= 2.6.12 and (Node.js >= 0.11.16 or io.js).

@@ -34,2 +34,4 @@ # Feature

* [Migrating from node_redis](https://github.com/luin/ioredis/wiki/Migrating-from-node_redis)
* [Error Handling](#error-handling)
* [Benchmark](#benchmark)

@@ -222,3 +224,3 @@ # Quick Start

```javascript
redis.pipeline().get('foo').mulit().set('foo', 'bar').get('foo').exec().get('foo').exec();
redis.pipeline().get('foo').multi().set('foo', 'bar').get('foo').exec().get('foo').exec();
```

@@ -436,3 +438,3 @@

but a few so that if one is down the client will try the next one, and the client will discover other nodes automatically when at least one node is connnected.
0. Some comands can't be used in the cluster mode, e.g. `info` and `pipeline`, custom commands also don't work(currently).
0. Some features are not available in the cluster mode, e.g. `pipeline` and custom commands(currently).

@@ -446,2 +448,78 @@ ## hiredis

# Error Handling
All the errors returned by the Redis server are instances of `ReplyError`, which can be accessed via `Redis`:
```javascript
var Redis = require('ioredis');
var redis = new Redis();
// This command causes an reply error since SET command requires two arguments.
redis.set('foo', function (err) {
// err instanceof Redis.ReplyError
});
```
When a reply error is not handled(no callback is specified and no `catch` method is chained),
the error will be logged to the stderr. For instance:
```javascript
var Redis = require('ioredis');
var redis = new Redis();
redis.set('foo');
```
The following error will be printed:
```
Unhandled rejection ReplyError: ERR wrong number of arguments for 'set' command
at ReplyParser._parseResult (/app/node_modules/ioredis/lib/parsers/javascript.js:60:14)
at ReplyParser.execute (/app/node_modules/ioredis/lib/parsers/javascript.js:178:20)
at Socket.<anonymous> (/app/node_modules/ioredis/lib/redis/event_handler.js:99:22)
at Socket.emit (events.js:97:17)
at readableAddChunk (_stream_readable.js:143:16)
at Socket.Readable.push (_stream_readable.js:106:10)
at TCP.onread (net.js:509:20)
```
But the error stack doesn't make any sense because the whole stack happens in the ioreids
module itself, not in your code. So it's not easy to find out where the error happens in your code.
ioredis provides an option `showFriendlyErrorStack` to solve the problem. When you enable
`showFriendlyErrorStack`, ioredis will optimize the error stack for you:
```javascript
var Redis = require('ioredis');
var redis = new Redis({ showFriendlyErrorStack: true });
redis.set('foo');
```
And the output will be:
```
Unhandled rejection ReplyError: ERR wrong number of arguments for 'set' command
at Object.<anonymous> (/app/index.js:3:7)
at Module._compile (module.js:446:26)
at Object.Module._extensions..js (module.js:464:10)
at Module.load (module.js:341:32)
at Function.Module._load (module.js:296:12)
at Function.Module.runMain (module.js:487:10)
at startup (node.js:111:16)
at node.js:799:3
```
This time the stack tells you that the error happens on the third line in your code, pretty sweet!
However, it would decrease the performance significantly to optimize the error stack. So by
default this option is disabled and can be only used for debug purpose. You **shouldn't** use this feature in production environment.
If you want to catch all unhandled errors without decrease performance, there's another way:
```javascript
var Redis = require('ioredis');
Redis.Promise.onPossiblyUnhandledRejection(function (error) {
// you can log the error here.
// error.command.name is the command name, here is 'set'
// error.command.args is the command arguments, here is ['foo']
});
var redis = new Redis();
redis.set('foo');
```
# Benchmark

@@ -453,25 +531,25 @@

> npm run bench
simple set
65,438 op/s » ioredis
36,954 op/s » node_redis
simple set
81,026 op/s » ioredis
43,487 op/s » node_redis
simple get
71,109 op/s » ioredis
36,825 op/s » node_redis
simple get
79,565 op/s » ioredis
41,808 op/s » node_redis
simple get with pipeline
11,123 op/s » ioredis
3,820 op/s » node_redis
simple get with pipeline
12,711 op/s » ioredis
4,714 op/s » node_redis
lrange 100
58,812 op/s » ioredis
46,703 op/s » node_redis
lrange 100
61,149 op/s » ioredis
48,827 op/s » node_redis
Suites: 4
Benches: 8
Elapsed: 61,715.11 ms
Suites: 4
Benches: 8
Elapsed: 57,882.94 ms
```
You can find the code at `benchmark.js`.
You can find the code at `benchmark.js` and run it yourself using `npm run bench`.

@@ -478,0 +556,0 @@ # Running tests

@@ -7,5 +7,11 @@ // var noderedis = require('redis');

var Redis = require('./');
// var redis = new Redis({ connectTimeout: 10 });
// // var redis = new Redis();
var redis = new Redis({ showFriendlyErrorStack: 10 });
// var redis = new Redis();
Redis.Promise.onPossiblyUnhandledRejection(function(error){
console.log(error);
});
redis.set('foo');
// var redis = new Redis();
// redis.blpop('que1', 0, function () {

@@ -46,12 +52,12 @@ // console.log(arguments);

var cluster = new Redis.Cluster([{
port: 6380,
host: '127.0.0.1'
}, {
port: 6381,
host: '127.0.0.1'
}]);
cluster.mget('foo13', 'foo', function (err, res) {
console.log(err, res);
});
// var cluster = new Redis.Cluster([{
// port: 6380,
// host: '127.0.0.1'
// }, {
// port: 6381,
// host: '127.0.0.1'
// }]);
// cluster.mget('foo13', 'foo', function (err, res) {
// console.log(err, res);
// });
// var redis = new Redis(6388, '177.22.22.2', {

@@ -58,0 +64,0 @@ // enableReadyCheck: false

@@ -27,3 +27,3 @@ var Command = require('../../lib/command');

it('should return buffer when replyEncoding is not set', function (done) {
var command = new Command('get', ['foo'], null, function (err, result) {
var command = new Command('get', ['foo'], { replyEncoding: null }, function (err, result) {
expect(result).to.be.instanceof(Buffer);

@@ -37,3 +37,3 @@ expect(result.toString()).to.eql('foo');

it('should covert result to string if replyEncoding is specified', function (done) {
var command = new Command('get', ['foo'], 'utf8', function (err, result) {
var command = new Command('get', ['foo'], { replyEncoding: 'utf8' }, function (err, result) {
expect(result).to.eql('foo');

@@ -47,3 +47,3 @@ done();

var base64 = new Buffer('foo').toString('base64');
var command = new Command('get', ['foo'], 'base64', function (err, result) {
var command = new Command('get', ['foo'], { replyEncoding: 'base64' }, function (err, result) {
expect(result).to.eql(base64);

@@ -50,0 +50,0 @@ done();

@@ -59,2 +59,7 @@ describe('Redis', function () {

option = getOption({
showFriendlyErrorStack: true
});
expect(option).to.have.property('showFriendlyErrorStack', true);
option = getOption(6380, {

@@ -61,0 +66,0 @@ host: '192.168.1.1'

@@ -116,2 +116,10 @@ var utils = require('../../lib/utils');

});
describe('.optimizeErrorStack', function () {
it('should return correctly', function () {
var error = new Error();
var res = utils.optimizeErrorStack(error, new Error().stack + '\n@', __dirname);
expect(res.stack.split('\n').pop()).to.eql('@');
});
});
});

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc