Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

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 0.2.0 to 0.3.0

LICENSE

16

lib/command.js

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

_this.name = name.toLowerCase();
_this.name = name;
_this.args = args ? _.flatten(args) : [];
var transformer = Command.transformer.argument[_this.name];
var transformer = Command._transformer.argument[_this.name];
if (transformer) {

@@ -114,3 +114,3 @@ _this.args = transformer(_this.args);

}
transformer = Command.transformer.reply[_this.name];
transformer = Command._transformer.reply[_this.name];
if (transformer) {

@@ -140,3 +140,3 @@ result = transformer(result);

Command.transformer = {
Command._transformer = {
argument: {},

@@ -146,2 +146,10 @@ reply: {}

Command.setArgumentTransformer = function (name, func) {
Command._transformer.argument[name] = func;
};
Command.setReplyTransformer = function (name, func) {
Command._transformer.reply[name] = func;
};
module.exports = Command;

@@ -101,3 +101,3 @@ var _ = require('lodash');

return promise.then(function (a) {
return promise.then(function () {
var data = '';

@@ -104,0 +104,0 @@ var writePending = _this.replyPending = _this._queue.length;

@@ -66,3 +66,5 @@ var _ = require('lodash');

function Redis(port, host, options) {
if (!(this instanceof Redis)) return new Redis(port, host, options);
if (!(this instanceof Redis)) {
return new Redis(port, host, options);
}

@@ -144,2 +146,28 @@ EventEmitter.call(this);

/**
* Default options
*
* @var _defaultOptions
* @memberOf Redis
* @private
*/
Redis._defaultOptions = {
port: 6379,
host: 'localhost',
family: 4,
enableOfflineQueue: true,
enableReadyCheck: true,
retryStrategy: function (times) {
var delay = Math.min(times * 2, 2000);
return delay;
},
password: null,
db: 0,
role: 'master',
sentinel: null,
roleRetryDelay: 500,
name: null
};
/**
* Create a connection to Redis.

@@ -267,3 +295,3 @@ * This method will be invoked automatically when creating a new Redis instance.

} else {
var retryTime = (obj.loading_eta_seconds || 1) * 1000;
var retryTime = (info.loading_eta_seconds || 1) * 1000;
debug('Redis server still loading, trying again in ' + retryTime + 'ms');

@@ -348,3 +376,3 @@ setTimeout(function () {

return new Promise(function (resolve, reject) {
return new Promise(function (resolve) {
monitorInstance.once('monitoring', function () {

@@ -486,4 +514,2 @@ resolve(monitorInstance);

_.assign(Redis, require('./redis/default_options'));
_.assign(Redis.prototype, require('./redis/prototype/parser'));

@@ -493,2 +519,41 @@

Redis.Command = Command;
Redis.Command.setArgumentTransformer('mset', function (args) {
if (args.length === 1) {
var pos = 1;
if (typeof Map !== 'undefined' && args[0] instanceof Map) {
return utils.convertMapToArray(args[0]);
}
if ( typeof args[0] === 'object' && args[0] !== null) {
return utils.convertObjectToArray(args[0]);
}
}
return args;
});
Redis.Command.setArgumentTransformer('hmset', function (args) {
if (args.length === 2) {
var pos = 1;
if (typeof Map !== 'undefined' && args[1] instanceof Map) {
return [args[0]].concat(utils.convertMapToArray(args[1]));
}
if ( typeof args[1] === 'object' && args[1] !== null) {
return [args[0]].concat(utils.convertObjectToArray(args[1]));
}
}
return args;
});
Redis.Command.setReplyTransformer('hgetall', function (result) {
if (Array.isArray(result)) {
var obj = {};
for (var i = 0; i < result.length; i += 2) {
obj[result[i]] = result[i + 1];
}
return obj;
}
return result;
});
var Sentinel = require('./sentinel');

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

while (offlineQueue.length > 0) {
item = offlineQueue.shift();
var item = offlineQueue.shift();
if (item.select !== self.condition.select && item.command.name !== 'select') {

@@ -151,0 +151,0 @@ self.sendCommand(new Command('select', [item.select]));

@@ -18,3 +18,5 @@ /** Test if two buffers are equal

for (var i = 0; i < a.length; ++i) {
if (a[i] !== b[i]) return false;
if (a[i] !== b[i]) {
return false;
}
}

@@ -99,3 +101,2 @@ return true;

var isValue = false;
for (var i = 1; i < length; i += 2) {

@@ -120,1 +121,25 @@ result[array[i - 1]] = array[i];

};
exports.convertObjectToArray = function (obj) {
var result = [];
var pos = 0;
for (var key in obj) {
if (obj.hasOwnProperty(key)) {
result[pos] = key;
result[pos + 1] = obj[key];
}
pos += 2;
}
return result;
};
exports.convertMapToArray = function (map) {
var result = [];
var pos = 0;
map.forEach(function (value, key) {
result[pos] = key;
result[pos + 1] = value;
pos += 2;
});
return result;
};
{
"name": "ioredis",
"version": "0.2.0",
"version": "0.3.0",
"description": "A delightful, performance-focused Redis client for Node and io.js",
"main": "index.js",
"scripts": {
"test": "mocha",
"test": "NODE_ENV=test mocha",
"test:debug": "NODE_ENV=test DEBUG=ioredis:* mocha",
"test:cov": "NODE_ENV=test node ./node_modules/istanbul/lib/cli.js cover --preserve-comments ./node_modules/mocha/bin/_mocha -- -R spec",
"generate-docs": "jsdoc --configure .jsdoc.json --verbose"

@@ -31,2 +33,4 @@ },

"chai": "^2.2.0",
"codeclimate-test-reporter": "0.0.4",
"istanbul": "^0.3.13",
"jsdoc": "^3.3.0-beta3",

@@ -33,0 +37,0 @@ "mocha": "^2.2.1",

# ioredis
[![Build Status](https://travis-ci.org/luin/ioredis.png?branch=master)](https://travis-ci.org/luin/ioredis)
[![Test Coverage](https://codeclimate.com/github/luin/ioredis/badges/coverage.svg)](https://codeclimate.com/github/luin/ioredis)
[![Dependency Status](https://david-dm.org/luin/ioredis.svg)](https://david-dm.org/luin/ioredis)

@@ -13,12 +14,12 @@ [![Join the chat at https://gitter.im/luin/ioredis](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/luin/ioredis?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)

ioredis is a robust, full-featured Redis client
used in the biggest online commerce company [Alibaba](http://www.alibaba.com/).
used in the world's biggest online commerce company [Alibaba](http://www.alibaba.com/).
0. Full-featured. It supports [Cluster](http://redis.io/topics/cluster-tutorial), [Sentinel](redis.io/topics/sentinel), [Pipelining](http://redis.io/topics/pipelining) and of course [Lua scripting](http://redis.io/commands/eval) & [Pub/Sub](http://redis.io/topics/pubsub)(with the support of binary messages).
0. Full-featured. It supports [Cluster](http://redis.io/topics/cluster-tutorial)(WIP), [Sentinel](redis.io/topics/sentinel), [Pipelining](http://redis.io/topics/pipelining) and of course [Lua scripting](http://redis.io/commands/eval) & [Pub/Sub](http://redis.io/topics/pubsub)(with the support of binary messages).
0. High performance.
0. Delightful API. Supports both Node-style callbacks and promises.
0. Supports Redis commands transform.
0. Supports command arguments and replies transform.
0. Abstraction for Lua scripting, allowing you to define custom commands.
0. Support for binary data.
0. Support for both TCP/IP and UNIX domain sockets.
0. Flexible system for defining custom command and registering command plugins.
0. Flexible system for registering command wrapper.
0. Supports offline queue and ready checking.

@@ -130,2 +131,66 @@ 0. Supports ES6 types such as `Map` and `Set`.

## Arguments & Replies Transform
Most Redis commands take one or more Strings as arguments,
and replies are sent back as a single String or an Array of Strings. However sometimes
you may want something different: For instance it would be more convenient if HGETALL
command returns a hash (e.g. `{key: val1, key2: v2}`) rather than an array of key values (e.g. `[key1,val1,key2,val2]`).
ioredis has a flexible system for transforming arguments and replies. There are two types
of transformers, argument transform and reply transformer:
```javascript
var Redis = require('ioredis');
// define a argument transformer that convert
// hmset('key', { k1: 'v1', k2: 'v2' })
// or
// hmset('key', new Map([['k1', 'v1'], ['k2', 'v2']]))
// into
// hmset('key', 'k1', 'v1', 'k2', 'v2')
Redis.Command.setArgumentTransformer('hmset', function (args) {
if (args.length === 2) {
var pos = 1;
if (typeof Map !== 'undefined' && args[1] instanceof Map) {
return [args[0]].concat(utils.convertMapToArray(args[1]));
}
if ( typeof args[1] === 'object' && args[1] !== null) {
return [args[0]].concat(utils.convertObjectToArray(args[1]));
}
}
return args;
});
// define a reply transformer that convert the reply
// ['k1', 'v1', 'k2', 'v2']
// into
// { k1: 'v1', 'k2': 'v2' }
Redis.Command.setReplyTransformer('hgetall', function (result) {
if (Array.isArray(result)) {
var obj = {};
for (var i = 0; i < result.length; i += 2) {
obj[result[i]] = result[i + 1];
}
return obj;
}
return result;
});
```
There are three built-in transformers, two argument transformer for `hmset` & `mset` and
a reply transformer for `hgetall`. Transformers for `hmset` and `hgetall` has been mentioned
above, and the transformer for `mset` is similar to the one for `hmset`:
```
redis.mset({ k1: 'v1', k2: 'v2' });
redis.get('k1', function (err, result) {
// result === 'v1';
});
redis.mset(new Map([['k3', 'v3'], ['k4', 'v4']]));
redis.get('k3', function (err, result) {
// result === 'v3';
});
```
## Pipelining

@@ -335,5 +400,5 @@ If you want to send a batch of commands(e.g. > 100), you can use pipelining to queue

ioredis **guarantees** that the node you connected to always be a master even after a failover. When a failover happens, instead of trying to reconnect with the failed node(which will be demoted to slave when it's available again), ioredis will ask sentinels for the new master node and connect to it. All commands sent during the failover are queued and will be executed when the new connection is established so that none of the commands will be lost.
ioredis **guarantees** that the node you connected with is always a master even after a failover. When a failover happens, instead of trying to reconnect with the failed node(which will be demoted to slave when it's available again), ioredis will ask sentinels for the new master node and connect to it. All commands sent during the failover are queued and will be executed when the new connection is established so that none of the commands will be lost.
It's possible to connect to a slave instead of a master by specifying a option `role` with the value of `slave`, and ioredis will try to connect to a random slave of the specified master, with the guarantee of the connected node is always a slave. If the current node is promoted to master because of a failover, ioredis will disconnect with it and ask sentinels for another slave node to connect to.
It's possible to connect to a slave instead of a master by specifying the option `role` with the value of `slave`, and ioredis will try to connect to a random slave of the specified master, with the guarantee that the connected node is always a slave. If the current node is promoted to master owing to a failover, ioredis will disconnect with it and ask sentinels for another slave node to connect to.

@@ -359,3 +424,3 @@ <hr>

client.on('message', function (msg) {
// Will print "Hello world", although no `publish` in invoked.
// Will print "Hello world", although no `publish` is invoked.
console.log('received ', msg);

@@ -366,1 +431,9 @@ });

I submitted some pull requests but sadly none of them has been merged, so here's ioredis.
# Acknowledge
The JavaScript and hiredis parsers are modified from [node_redis](https://github.com/mranney/node_redis) (MIT License, Copyright (c) 2010 Matthew Ranney, http://ranney.com/).
# License
MIT

@@ -14,10 +14,10 @@ GLOBAL.expect = require('chai').expect;

// afterEach(function (done) {
// var redis = new Redis();
// redis.flushall(function () {
// redis.script('flush', function () {
// redis.disconnect();
// done();
// });
// });
// });
afterEach(function (done) {
var redis = new Redis();
redis.flushall(function () {
redis.script('flush', function () {
redis.disconnect();
done();
});
});
});

@@ -5,9 +5,2 @@ var Command = require('../../lib/command');

describe('constructor()', function () {
it('should reject when the command isnt a string', function () {
var command = new Command(123);
return command.promise.catch(function (err) {
expect(err).to.be.instanceof(Error);
});
});
it('should flatten the args', function () {

@@ -14,0 +7,0 @@ var command = new Command('get', ['foo', ['bar', ['zoo']]]);

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