[api] More work on Redis store
This commit is contained in:
parent
67b5c8ab2a
commit
4c8e7a5b7f
2 changed files with 165 additions and 4 deletions
|
@ -6,11 +6,13 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
var async = require('async'),
|
var async = require('async'),
|
||||||
|
eyes = require('eyes'),
|
||||||
redis = require('redis'),
|
redis = require('redis'),
|
||||||
nconf = require('nconf'),
|
nconf = require('nconf'),
|
||||||
Memory = require('./Memory').Memory;
|
Memory = require('./Memory').Memory;
|
||||||
|
|
||||||
var Redis = exports.Redis = function (options) {
|
var Redis = exports.Redis = function (options) {
|
||||||
|
options = options || {}
|
||||||
this.namespace = options.namespace || 'nconf';
|
this.namespace = options.namespace || 'nconf';
|
||||||
this.host = options.host || 'localhost';
|
this.host = options.host || 'localhost';
|
||||||
this.port = options.port || 6379;
|
this.port = options.port || 6379;
|
||||||
|
@ -19,7 +21,33 @@ var Redis = exports.Redis = function (options) {
|
||||||
};
|
};
|
||||||
|
|
||||||
Redis.prototype.get = function (key, callback) {
|
Redis.prototype.get = function (key, callback) {
|
||||||
|
var self = this,
|
||||||
|
result = {},
|
||||||
|
fullKey = nconf.utils.key(this.namespace, key);
|
||||||
|
|
||||||
|
this.redis.smembers(nconf.utils.key(fullKey, 'keys'), function (err, keys) {
|
||||||
|
function addValue (source, next) {
|
||||||
|
self.get(nconf.utils.key(key, source), function (err, value) {
|
||||||
|
if (err) {
|
||||||
|
return next(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
result[source] = value;
|
||||||
|
next();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (keys && keys.length > 0) {
|
||||||
|
async.forEach(keys, addValue, function (err) {
|
||||||
|
return err ? callback(err) : callback(null, result);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
self.redis.get(fullKey, function (err, value) {
|
||||||
|
return err ? callback(err) : callback(null, JSON.parse(value));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
Redis.prototype.set = function (key, value, callback) {
|
Redis.prototype.set = function (key, value, callback) {
|
||||||
|
@ -29,20 +57,56 @@ Redis.prototype.set = function (key, value, callback) {
|
||||||
function addKey (partial, next) {
|
function addKey (partial, next) {
|
||||||
var index = path.indexOf(partial),
|
var index = path.indexOf(partial),
|
||||||
base = [self.namespace].concat(path.slice(0, index)),
|
base = [self.namespace].concat(path.slice(0, index)),
|
||||||
parent = nconf.utils.key(base.concat('keys'));
|
parent = nconf.utils.key(base.concat(['keys']));
|
||||||
|
|
||||||
self.redis.rpush(parent, partial, next);
|
self.redis.sadd(parent, partial, next);
|
||||||
};
|
};
|
||||||
|
|
||||||
async.forEach(path, addKey, function (err) {
|
async.forEach(path, addKey, function (err) {
|
||||||
if (err) {
|
if (err) {
|
||||||
return callback(err);
|
return callback(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var fullKey = nconf.utils.key(self.namespace, key);
|
||||||
|
|
||||||
|
if (!Array.isArray(value) && typeof value === 'object') {
|
||||||
|
self._setObject(fullKey, value, callback);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
value = JSON.stringify(value);
|
||||||
|
self.redis.set(fullKey, value, callback);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
Redis.prototype.clear = function (key, callback) {
|
Redis.prototype.clear = function (key, callback) {
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Redis.prototype._setObject = function (key, value, callback) {
|
||||||
|
var self = this,
|
||||||
|
keys = Object.keys(value);
|
||||||
|
|
||||||
|
function addValue (child, next) {
|
||||||
|
self.redis.sadd(nconf.utils.key(key, 'keys'), child, function (err) {
|
||||||
|
if (err) {
|
||||||
|
return next(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
var fullKey = nconf.utils.key(key, child),
|
||||||
|
childValue = value[child];
|
||||||
|
|
||||||
|
if (!Array.isArray(childValue) && typeof childValue === 'object') {
|
||||||
|
self._setObject(fullKey, childValue, next);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
childValue = JSON.stringify(childValue);
|
||||||
|
self.redis.set(fullKey, childValue, next);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async.forEach(keys, addValue, function (err) {
|
||||||
|
return err ? callback(err) : callback();
|
||||||
|
});
|
||||||
|
};
|
97
test/stores/redis-test.js
Normal file
97
test/stores/redis-test.js
Normal file
|
@ -0,0 +1,97 @@
|
||||||
|
/*
|
||||||
|
* redis-test.js: Tests for the redis nconf storage engine.
|
||||||
|
*
|
||||||
|
* (C) 2011, Charlie Robbins
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
require.paths.unshift(require('path').join(__dirname, '..', '..', 'lib'));
|
||||||
|
|
||||||
|
var vows = require('vows'),
|
||||||
|
assert = require('assert'),
|
||||||
|
nconf = require('nconf');
|
||||||
|
|
||||||
|
var data = {
|
||||||
|
literal: 'bazz',
|
||||||
|
arr: ['one', 2, true, { value: 'foo' }],
|
||||||
|
obj: {
|
||||||
|
host: 'localhost',
|
||||||
|
port: 5984,
|
||||||
|
array: ['one', 2, true, { foo: 'bar' }],
|
||||||
|
auth: {
|
||||||
|
username: 'admin',
|
||||||
|
password: 'password'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
vows.describe('nconf/stores/redis').addBatch({
|
||||||
|
"When using the nconf redis store": {
|
||||||
|
topic: new nconf.stores.Redis(),
|
||||||
|
"the set() method": {
|
||||||
|
"with a literal": {
|
||||||
|
topic: function (store) {
|
||||||
|
store.set('foo:literal', 'bazz', this.callback)
|
||||||
|
},
|
||||||
|
"should respond without an error": function (err, ok) {
|
||||||
|
assert.isNull(err);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"with an Array": {
|
||||||
|
topic: function (store) {
|
||||||
|
store.set('foo:array', data.arr, this.callback)
|
||||||
|
},
|
||||||
|
"should respond without an": function (err, ok) {
|
||||||
|
assert.isNull(err);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"with an Object": {
|
||||||
|
topic: function (store) {
|
||||||
|
store.set('foo:object', data.obj, this.callback)
|
||||||
|
},
|
||||||
|
"should respond without an error": function (err, ok) {
|
||||||
|
assert.isNull(err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}).addBatch({
|
||||||
|
"When using the nconf redis store": {
|
||||||
|
topic: new nconf.stores.Redis(),
|
||||||
|
"the get() method": {
|
||||||
|
"with a literal value": {
|
||||||
|
topic: function (store) {
|
||||||
|
store.get('foo:literal', this.callback);
|
||||||
|
},
|
||||||
|
"should respond with the correct value": function (err, value) {
|
||||||
|
assert.equal(value, data.literal);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"with an Array value": {
|
||||||
|
topic: function (store) {
|
||||||
|
store.get('foo:array', this.callback);
|
||||||
|
},
|
||||||
|
"should respond with the correct value": function (err, value) {
|
||||||
|
assert.deepEqual(value, data.arr);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"with an Object value": {
|
||||||
|
topic: function (store) {
|
||||||
|
store.get('foo:object', this.callback);
|
||||||
|
},
|
||||||
|
"should respond with the correct value": function (err, value) {
|
||||||
|
assert.deepEqual(value, data.obj);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}).addBatch({
|
||||||
|
/*,
|
||||||
|
"the clear() method": {
|
||||||
|
"should respond with the true": function (store) {
|
||||||
|
assert.equal(store.get('foo:bar:bazz'), 'buzz');
|
||||||
|
assert.isTrue(store.clear('foo:bar:bazz'));
|
||||||
|
assert.isTrue(typeof store.get('foo:bar:bazz') === 'undefined');
|
||||||
|
}
|
||||||
|
}*/
|
||||||
|
}).export(module);
|
Loading…
Reference in a new issue