Browse Source

reluctantly converting to camelcase

feature/specify-what-to-cache
Bryan Donovan 10 years ago
parent
commit
3b127c2c9f
  1. 1
      .jscs.json
  2. 76
      README.md
  3. 68
      examples/example.js
  4. 50
      examples/redis_example/example.js
  5. 10
      examples/redis_example/redis_store.js
  6. 3
      index.js
  7. 4
      lib/caching.js
  8. 53
      lib/multi_caching.js
  9. 18
      lib/stores/memory.js
  10. 226
      test/caching.unit.js
  11. 410
      test/multi_caching.unit.js
  12. 26
      test/run.js
  13. 6
      test/stores/memory.unit.js
  14. 22
      test/stores/options.unit.js
  15. 34
      test/support.js

1
.jscs.json

@ -12,6 +12,7 @@
"requireSpaceAfterBinaryOperators": ["?", "+", "/", "*", "=", "==", "===", "!=", "!==", ">", ">=", "<", "<="],
"disallowSpaceAfterBinaryOperators": ["!"],
"disallowSpaceBeforeBinaryOperators": [","],
"requireCamelCaseOrUpperCaseIdentifiers": true,
"disallowMultipleVarDecl": true,
"disallowEmptyBlocks": true,

76
README.md

@ -35,17 +35,17 @@ First, it includes a `wrap` function that lets you wrap any function in cache.
This is probably the feature you're looking for. As an example, where you might have to do this:
```javascript
function get_cached_user(id, cb) {
memory_cache.get(id, function (err, result) {
function getCachedUser(id, cb) {
memoryCache.get(id, function (err, result) {
if (err) { return cb(err); }
if (result) {
return cb(null, result);
}
get_user(id, function (err, result) {
getUser(id, function (err, result) {
if (err) { return cb(err); }
memory_cache.set(id, result);
memoryCache.set(id, result);
cb(null, result);
});
});
@ -54,9 +54,9 @@ function get_cached_user(id, cb) {
... you can instead use the `wrap` function:
```javascript
function get_cached_user(id, cb) {
memory_cache.wrap(id, function (cache_callback) {
get_user(id, cache_callback);
function getCachedUser(id, cb) {
memoryCache.wrap(id, function (cacheCallback) {
getUser(id, cacheCallback);
}, ttl, cb);
}
```
@ -86,40 +86,40 @@ Redis cache store with connection pooling.
### Single Store
```javascript
var cache_manager = require('cache-manager');
var memory_cache = cache_manager.caching({store: 'memory', max: 100, ttl: 10/*seconds*/});
var cacheManager = require('cache-manager');
var memoryCache = cacheManager.caching({store: 'memory', max: 100, ttl: 10/*seconds*/});
var ttl = 5;
// Note: callback is optional in set() and del().
memory_cache.set('foo', 'bar', ttl, function(err) {
memoryCache.set('foo', 'bar', ttl, function(err) {
if (err) { throw err; }
memory_cache.get('foo', function(err, result) {
memoryCache.get('foo', function(err, result) {
console.log(result);
// >> 'bar'
memory_cache.del('foo', function(err) {});
memoryCache.del('foo', function(err) {});
});
});
function get_user(id, cb) {
function getUser(id, cb) {
setTimeout(function () {
console.log("Returning user from slow database.");
cb(null, {id: id, name: 'Bob'});
}, 100);
}
var user_id = 123;
var key = 'user_' + user_id;
var userId = 123;
var key = 'user_' + userId;
// Note: ttl is optional in wrap()
memory_cache.wrap(key, function (cb) {
get_user(user_id, cb);
memoryCache.wrap(key, function (cb) {
getUser(userId, cb);
}, ttl, function (err, user) {
console.log(user);
// Second time fetches user from memory_cache
memory_cache.wrap(key, function (cb) {
get_user(user_id, cb);
// Second time fetches user from memoryCache
memoryCache.wrap(key, function (cb) {
getUser(userId, cb);
}, function (err, user) {
console.log(user);
});
@ -143,10 +143,10 @@ function respond(res, err, data) {
}
app.get('/foo/bar', function(req, res) {
var cache_key = 'foo-bar:' + JSON.stringify(req.query);
var cacheKey = 'foo-bar:' + JSON.stringify(req.query);
var ttl = 10;
memory_cache.wrap(cache_key, function(cache_cb) {
DB.find(req.query, cache_cb);
memoryCache.wrap(cacheKey, function(cacheCallback) {
DB.find(req.query, cacheCallback);
}, ttl, function(err, result) {
respond(res, err, result);
});
@ -162,45 +162,45 @@ in an instance of it, or pass in the path to the module.
E.g.,
```javascript
var my_store = require('your-homemade-store');
var cache = cache_manager.caching({store: my_store});
var myStore = require('your-homemade-store');
var cache = cacheManager.caching({store: myStore});
// or
var cache = cache_manager.caching({store: '/path/to/your/store'});
var cache = cacheManager.caching({store: '/path/to/your/store'});
```
### Multi-Store
```javascript
var multi_cache = cache_manager.multi_caching([memory_cache, some_other_cache]);
user_id2 = 456;
key2 = 'user_' + user_id;
var multiCache = cacheManager.multiCaching([memoryCache, someOtherCache]);
userId2 = 456;
key2 = 'user_' + userId;
ttl = 5;
// Sets in all caches.
multi_cache.set('foo2', 'bar2', ttl, function(err) {
multiCache.set('foo2', 'bar2', ttl, function(err) {
if (err) { throw err; }
// Fetches from highest priority cache that has the key.
multi_cache.get('foo2', function(err, result) {
multiCache.get('foo2', function(err, result) {
console.log(result);
// >> 'bar2'
// Delete from all caches
multi_cache.del('foo2');
multiCache.del('foo2');
});
});
// Note: ttl is optional in wrap()
multi_cache.wrap(key2, function (cb) {
get_user(user_id2, cb);
multiCache.wrap(key2, function (cb) {
getUser(userId2, cb);
}, ttl, function (err, user) {
console.log(user);
// Second time fetches user from memory_cache, since it's highest priority.
// Second time fetches user from memoryCache, since it's highest priority.
// If the data expires in the memory cache, the next fetch would pull it from
// the 'some_other_cache', and set the data in memory again.
multi_cache.wrap(key2, function (cb) {
get_user(user_id2, cb);
// the 'someOtherCache', and set the data in memory again.
multiCache.wrap(key2, function (cb) {
getUser(userId2, cb);
}, function (err, user) {
console.log(user);
});

68
examples/example.js

@ -1,20 +1,20 @@
/*jshint unused:false*/
// Note: ttls are in seconds
var cache_manager = require('../');
var memory_cache = cache_manager.caching({store: 'memory', max: 100, ttl: 10});
var memory_cache2 = cache_manager.caching({store: 'memory', max: 100, ttl: 100});
var cacheManager = require('../');
var memoryCache = cacheManager.caching({store: 'memory', max: 100, ttl: 10});
var memoryCache2 = cacheManager.caching({store: 'memory', max: 100, ttl: 100});
var ttl; //Can't use a different ttl per set() call with memory cache
//
// Basic usage
//
memory_cache.set('foo', 'bar', ttl, function(err) {
memoryCache.set('foo', 'bar', ttl, function(err) {
if (err) { throw err; }
memory_cache.get('foo', function(err, result) {
memoryCache.get('foo', function(err, result) {
console.log(result);
// >> 'bar'
memory_cache.del('foo', function(err) {
memoryCache.del('foo', function(err) {
if (err) {
console.log(err);
}
@ -22,49 +22,49 @@ memory_cache.set('foo', 'bar', ttl, function(err) {
});
});
function get_user(id, cb) {
function getUser(id, cb) {
setTimeout(function() {
console.log("Fetching user from slow database.");
cb(null, {id: id, name: 'Bob'});
}, 100);
}
var user_id = 123;
var key = 'user_' + user_id;
var userId = 123;
var key = 'user_' + userId;
//
// wrap() example
//
// Instead of manually managing the cache like this:
function get_cached_user_manually(id, cb) {
memory_cache.get(id, function(err, result) {
function getCachedUserManually(id, cb) {
memoryCache.get(id, function(err, result) {
if (err) { return cb(err); }
if (result) {
return cb(null, result);
}
get_user(id, function(err, result) {
getUser(id, function(err, result) {
if (err) { return cb(err); }
memory_cache.set(id, result);
memoryCache.set(id, result);
cb(null, result);
});
});
}
// ... you can instead use the `wrap` function:
function get_cached_user(id, cb) {
memory_cache.wrap(id, function(cache_callback) {
get_user(id, cache_callback);
function getCachedUser(id, cb) {
memoryCache.wrap(id, function(cacheCallback) {
getUser(id, cacheCallback);
}, cb);
}
get_cached_user(user_id, function(err, user) {
getCachedUser(userId, function(err, user) {
// First time fetches the user from the (fake) database:
console.log(user);
get_cached_user(user_id, function(err, user) {
getCachedUser(userId, function(err, user) {
// Second time fetches from cache.
console.log(user);
});
@ -76,14 +76,14 @@ get_cached_user(user_id, function(err, user) {
// { id: 123, name: 'Bob' }
// Same as above, but written differently:
memory_cache.wrap(key, function(cb) {
get_user(user_id, cb);
memoryCache.wrap(key, function(cb) {
getUser(userId, cb);
}, function(err, user) {
console.log(user);
// Second time fetches user from memory_cache
memory_cache.wrap(key, function(cb) {
get_user(user_id, cb);
// Second time fetches user from memoryCache
memoryCache.wrap(key, function(cb) {
getUser(userId, cb);
}, function(err, user) {
console.log(user);
});
@ -92,36 +92,36 @@ memory_cache.wrap(key, function(cb) {
//
// multi-cache example
//
var multi_cache = cache_manager.multi_caching([memory_cache, memory_cache2]);
var user_id2 = 456;
var key2 = 'user_' + user_id;
var multiCache = cacheManager.multiCaching([memoryCache, memoryCache2]);
var userId2 = 456;
var key2 = 'user_' + userId;
var ttl2; //Can't use a different ttl per set() call with memory cache
multi_cache.wrap(key2, function(cb) {
get_user(user_id2, cb);
multiCache.wrap(key2, function(cb) {
getUser(userId2, cb);
}, function(err, user) {
console.log(user);
// Second time fetches user from memory_cache, since it's highest priority.
// Second time fetches user from memoryCache, since it's highest priority.
// If the data expires in the memory cache, the next fetch would pull it from
// the Redis cache, and set the data in memory again.
multi_cache.wrap(key2, function(cb) {
get_user(user_id2, cb);
multiCache.wrap(key2, function(cb) {
getUser(userId2, cb);
}, function(err, user) {
console.log(user);
});
// Sets in all caches.
multi_cache.set('foo2', 'bar2', ttl2, function(err) {
multiCache.set('foo2', 'bar2', ttl2, function(err) {
if (err) { throw err; }
// Fetches from highest priority cache that has the key.
multi_cache.get('foo2', function(err, result) {
multiCache.get('foo2', function(err, result) {
console.log(result);
// >> 'bar2'
// Delete from all caches
multi_cache.del('foo2', function(err) {
multiCache.del('foo2', function(err) {
if (err) {
console.log(err);
}

50
examples/redis_example/example.js

@ -3,88 +3,88 @@
// node examples/redis_example/example.js
var util = require('util');
var cache_manager = require('../../');
var redis_store = require('./redis_store');
var cacheManager = require('../../');
var redisStore = require('./redis_store');
// Note: ttl is in seconds
var redis_cache = cache_manager.caching({store: redis_store, db: 0, ttl: 100});
var redisCache = cacheManager.caching({store: redisStore, db: 0, ttl: 100});
var ttl = 60;
console.log("set/get/del example:");
redis_cache.set('foo', 'bar', {ttl: ttl}, function(err) {
redisCache.set('foo', 'bar', {ttl: ttl}, function(err) {
if (err) { throw err; }
redis_cache.get('foo', function(err, result) {
redisCache.get('foo', function(err, result) {
if (err) { throw err; }
console.log("result fetched from cache: " + result);
// >> 'bar'
redis_cache.del('foo', function(err) {
redisCache.del('foo', function(err) {
if (err) { throw err; }
});
});
});
// TTL defaults to what we passed into the caching function (100)
redis_cache.set('foo-no-ttl', 'bar-no-ttl', function(err) {
redisCache.set('foo-no-ttl', 'bar-no-ttl', function(err) {
if (err) { throw err; }
redis_cache.get('foo-no-ttl', function(err, result) {
redisCache.get('foo-no-ttl', function(err, result) {
if (err) { throw err; }
console.log("result fetched from cache: " + result);
// >> 'bar'
redis_cache.del('foo-no-ttl', function(err) {
redisCache.del('foo-no-ttl', function(err) {
if (err) { throw err; }
});
});
});
// Calls Redis 'set' instead of 'setex'
redis_cache.set('foo-zero-ttl', 'bar-zero-ttl', {ttl: 0}, function(err) {
redisCache.set('foo-zero-ttl', 'bar-zero-ttl', {ttl: 0}, function(err) {
if (err) { throw err; }
redis_cache.get('foo-zero-ttl', function(err, result) {
redisCache.get('foo-zero-ttl', function(err, result) {
if (err) { throw err; }
console.log("result fetched from cache: " + result);
// >> 'bar'
redis_cache.del('foo-zero-ttl', function(err) {
redisCache.del('foo-zero-ttl', function(err) {
if (err) { throw err; }
});
});
});
var user_id = 123;
var userId = 123;
function create_key(id) {
function createKey(id) {
return 'user_' + id;
}
function get_user(id, cb) {
function getUser(id, cb) {
setTimeout(function() {
console.log("\n\nReturning user from slow database.");
cb(null, {id: id, name: 'Bob'});
}, 100);
}
function get_user_from_cache(id, cb) {
var key = create_key(id);
redis_cache.wrap(key, function(cache_cb) {
get_user(user_id, cache_cb);
function getUserFromCache(id, cb) {
var key = createKey(id);
redisCache.wrap(key, function(cacheCb) {
getUser(userId, cacheCb);
}, {ttl: ttl}, cb);
}
get_user_from_cache(user_id, function(err, user) {
getUserFromCache(userId, function(err, user) {
console.log(user);
// Second time fetches user from redis_cache
get_user_from_cache(user_id, function(err, user) {
// Second time fetches user from redisCache
getUserFromCache(userId, function(err, user) {
console.log("user from second cache request:");
console.log(user);
redis_cache.keys(function(err, keys) {
redisCache.keys(function(err, keys) {
console.log("keys: " + util.inspect(keys));
var key = create_key(user_id);
redis_cache.del(key, function(err) {
var key = createKey(userId);
redisCache.del(key, function(err) {
if (err) { throw err; }
process.exit();
});

10
examples/redis_example/redis_store.js

@ -5,19 +5,21 @@
var RedisPool = require('sol-redis-pool');
function redis_store(args) {
function redisStore(args) {
args = args || {};
var self = {};
var ttlDefault = args.ttl;
self.name = 'redis';
self.client = require('redis').createClient(args.port, args.host, args);
var redis_options = {
//jscs:disable requireCamelCaseOrUpperCaseIdentifiers
var redisOptions = {
redis_host: args.host || '127.0.0.1',
redis_port: args.port || 6379
};
//jscs:enable requireCamelCaseOrUpperCaseIdentifiers
var pool = new RedisPool(redis_options);
var pool = new RedisPool(redisOptions);
function connect(cb) {
pool.acquire(function(err, conn) {
@ -108,6 +110,6 @@ function redis_store(args) {
module.exports = {
create: function(args) {
return redis_store(args);
return redisStore(args);
}
};

3
index.js

@ -1,6 +1,7 @@
var cache = {
caching: require('./lib/caching'),
multi_caching: require('./lib/multi_caching')
multi_caching: require('./lib/multi_caching'), //backward compat
multiCaching: require('./lib/multi_caching')
};
module.exports = cache;

4
lib/caching.js

@ -15,8 +15,8 @@ var caching = function(args) {
} else if (typeof args.store === 'string' && args.store.match(/\//)) {
self.store = require(args.store).create(args);
} else {
var store_name = args.store || 'memory';
self.store = require('./stores/' + store_name).create(args);
var storeName = args.store || 'memory';
self.store = require('./stores/' + storeName).create(args);
}
// do we handle a cache error the same as a cache miss?

53
lib/multi_caching.js

@ -5,22 +5,22 @@ var CallbackFiller = require('./callback_filler');
/**
* Module that lets you specify a hierarchy of caches.
*/
var multi_caching = function(caches) {
var multiCaching = function(caches) {
var self = {};
if (!Array.isArray(caches)) {
throw new Error('multi_caching requires an array of caches');
throw new Error('multiCaching requires an array of caches');
}
var callbackFiller = new CallbackFiller();
function get_from_highest_priority_cache(key, options, cb) {
function getFromHighestPriorityCache(key, options, cb) {
if (typeof options === 'function') {
cb = options;
options = undefined;
}
var i = 0;
async.eachSeries(caches, function(cache, async_cb) {
async.eachSeries(caches, function(cache, next) {
var callback = function(err, result) {
if (err) {
return cb(err);
@ -31,7 +31,7 @@ var multi_caching = function(caches) {
}
i += 1;
async_cb(err);
next(err);
};
if (typeof options === 'object') {
cache.store.get(key, options, callback);
@ -41,12 +41,12 @@ var multi_caching = function(caches) {
}, cb);
}
function set_in_multiple_caches(caches, opts, cb) {
async.each(caches, function(cache, async_cb) {
function setInMultipleCaches(caches, opts, cb) {
async.each(caches, function(cache, next) {
if (typeof opts.options !== 'object') {
cache.store.set(opts.key, opts.value, opts.ttl, async_cb);
cache.store.set(opts.key, opts.value, opts.ttl, next);
} else {
cache.store.set(opts.key, opts.value, opts.options, async_cb);
cache.store.set(opts.key, opts.value, opts.options, next);
}
}, cb);
}
@ -56,8 +56,8 @@ var multi_caching = function(caches) {
*
* When a key is found in a lower cache, all higher levels are updated
*/
self.get_and_pass_up = function(key, cb) {
get_from_highest_priority_cache(key, function(err, result, index) {
self.getAndPassUp = function(key, cb) {
getFromHighestPriorityCache(key, function(err, result, index) {
if (err) {
return cb(err);
}
@ -66,13 +66,20 @@ var multi_caching = function(caches) {
if (result !== undefined && index) {
var cachesToUpdate = caches.slice(0, index);
async.each(cachesToUpdate, function(cache, async_cb) {
cache.set(key, result, result.ttl, async_cb);
async.each(cachesToUpdate, function(cache, next) {
cache.set(key, result, result.ttl, next);
});
}
});
};
/**
* This is for backward-compatibility
*/
//jscs:disable requireCamelCaseOrUpperCaseIdentifiers
self.get_and_pass_up = self.getAndPassUp;
//jscs:enable requireCamelCaseOrUpperCaseIdentifiers
/**
* Wraps a function in one or more caches.
* Has same API as regular caching module.
@ -96,11 +103,11 @@ var multi_caching = function(caches) {
callbackFiller.queues[key] = [{cb: cb, domain: process.domain}];
get_from_highest_priority_cache(key, function(err, result, index) {
getFromHighestPriorityCache(key, function(err, result, index) {
if (err) {
return callbackFiller.fill(key, err);
} else if (result) {
var caches_to_update = caches.slice(0, index);
var cachesToUpdate = caches.slice(0, index);
var opts = {
key: key,
value: result,
@ -111,7 +118,7 @@ var multi_caching = function(caches) {
opts.ttl = options;
}
set_in_multiple_caches(caches_to_update, opts, function(err) {
setInMultipleCaches(cachesToUpdate, opts, function(err) {
callbackFiller.fill(key, err, result);
});
} else {
@ -134,7 +141,7 @@ var multi_caching = function(caches) {
if (typeof options !== 'object') {
opts.ttl = options;
}
set_in_multiple_caches(caches, opts, function(err) {
setInMultipleCaches(caches, opts, function(err) {
if (err) {
callbackFiller.fill(key, err);
} else {
@ -155,7 +162,7 @@ var multi_caching = function(caches) {
if (typeof options !== 'object') {
opts.ttl = options;
}
set_in_multiple_caches(caches, opts, cb);
setInMultipleCaches(caches, opts, cb);
};
self.get = function(key, options, cb) {
@ -163,7 +170,7 @@ var multi_caching = function(caches) {
cb = options;
options = false;
}
get_from_highest_priority_cache(key, options, cb);
getFromHighestPriorityCache(key, options, cb);
};
self.del = function(key, options, cb) {
@ -171,11 +178,11 @@ var multi_caching = function(caches) {
cb = options;
options = false;
}
async.each(caches, function(cache, async_cb) {
async.each(caches, function(cache, next) {
if (typeof options === 'object') {
cache.store.del(key, options, async_cb);
cache.store.del(key, options, next);
} else {
cache.store.del(key, async_cb);
cache.store.del(key, next);
}
}, cb);
};
@ -183,4 +190,4 @@ var multi_caching = function(caches) {
return self;
};
module.exports = multi_caching;
module.exports = multiCaching;

18
lib/stores/memory.js

@ -1,19 +1,19 @@
var Lru = require("lru-cache");
var memory_store = function(args) {
var memoryStore = function(args) {
args = args || {};
var self = {};
self.name = 'memory';
var ttl = args.ttl;
var lru_opts = {
var lruOpts = {
max: args.max || 500,
maxAge: ttl ? ttl * 1000 : null
};
var lru_cache = new Lru(lru_opts);
var lruCache = new Lru(lruOpts);
self.set = function(key, value, options, cb) {
lru_cache.set(key, value);
lruCache.set(key, value);
if (cb) {
process.nextTick(cb);
}
@ -23,7 +23,7 @@ var memory_store = function(args) {
if (typeof options === 'function') {
cb = options;
}
var value = lru_cache.get(key);
var value = lruCache.get(key);
if (cb) {
process.nextTick(function() {
cb(null, value);
@ -37,21 +37,21 @@ var memory_store = function(args) {
if (typeof options === 'function') {
cb = options;
}
lru_cache.del(key);
lruCache.del(key);
if (cb) {
process.nextTick(cb);
}
};
self.reset = function(cb) {
lru_cache.reset();
lruCache.reset();
if (cb) {
process.nextTick(cb);
}
};
self.keys = function(cb) {
var keys = lru_cache.keys();
var keys = lruCache.keys();
if (cb) {
process.nextTick(function() {
cb(null, keys);
@ -66,7 +66,7 @@ var memory_store = function(args) {
var methods = {
create: function(args) {
return memory_store(args);
return memoryStore(args);
}
};

226
test/caching.unit.js

@ -4,12 +4,12 @@ var assert = require('assert');
var async = require('async');
var sinon = require('sinon');
var support = require('./support');
var check_err = support.check_err;
var checkErr = support.checkErr;
var caching = require('../index').caching;
var memory_store = require('../lib/stores/memory');
var memoryStore = require('../lib/stores/memory');
var methods = {
get_widget: function(name, cb) {
getWidget: function(name, cb) {
cb(null, {name: name});
}
};
@ -32,7 +32,7 @@ describe("caching", function() {
it("lets us set and get data in cache", function(done) {
cache.set(key, value, ttl, function(err) {
check_err(err);
checkErr(err);
cache.get(key, function(err, result) {
assert.equal(result, value);
done();
@ -69,7 +69,7 @@ describe("caching", function() {
key = support.random.string(20);
value = support.random.string();
cache.set(key, value, ttl, function(err) {
check_err(err);
checkErr(err);
done();
});
});
@ -79,7 +79,7 @@ describe("caching", function() {
assert.equal(result, value);
cache.del(key, function(err) {
check_err(err);
checkErr(err);
cache.get(key, function(err, result) {
assert.ok(!result);
@ -116,7 +116,7 @@ describe("caching", function() {
key = support.random.string(20);
value = support.random.string();
cache.set(key, value, ttl, function(err) {
check_err(err);
checkErr(err);
key2 = support.random.string(20);
value2 = support.random.string();
@ -127,7 +127,7 @@ describe("caching", function() {
it("clears the cache", function(done) {
cache.reset(function(err) {
check_err(err);
checkErr(err);
cache.get(key, function(err, result) {
assert.ok(!result);
@ -155,10 +155,10 @@ describe("caching", function() {
});
context("when store has no del() method", function() {
var fake_store;
var fakeStore;
beforeEach(function() {
fake_store = {
fakeStore = {
get: function() {},
set: function() {},
};
@ -166,52 +166,52 @@ describe("caching", function() {
it("it doesn't throw an error", function() {
assert.doesNotThrow(function() {
caching({store: fake_store});
caching({store: fakeStore});
});
});
});
});
describe("setex()", function() {
var fake_store;
var fakeStore;
beforeEach(function() {
fake_store = {
fakeStore = {
get: function() {},
set: function() {},
del: function() {},
setex: function() {}
};
sinon.stub(fake_store, 'setex');
sinon.stub(fakeStore, 'setex');
cache = caching({store: fake_store});
cache = caching({store: fakeStore});
});
it("passes the params to the underlying store's setex() method", function() {
cache.setex('foo', 'bar', 'blah');
assert.ok(fake_store.setex.calledWith('foo', 'bar', 'blah'));
assert.ok(fakeStore.setex.calledWith('foo', 'bar', 'blah'));
});
});
describe("keys()", function() {
var key_count;
var saved_keys = [];
var keyCount;
var savedKeys = [];
beforeEach(function(done) {
key_count = 10;
keyCount = 10;
var processed = 0;
cache = caching({store: 'memory'});
function is_done() {
return processed === key_count;
function isDone() {
return processed === keyCount;
}
async.until(is_done, function(cb) {
async.until(isDone, function(cb) {
processed += 1;
key = support.random.string(20);
saved_keys.push(key);
savedKeys.push(key);
value = support.random.string();
cache.set(key, value, ttl, cb);
}, done);
@ -219,27 +219,27 @@ describe("caching", function() {
it("calls back with all keys in cache", function(done) {
cache.keys(function(err, keys) {
check_err(err);
assert.deepEqual(keys.sort, saved_keys.sort);
checkErr(err);
assert.deepEqual(keys.sort, savedKeys.sort);
done();
});
});
it("lets us get the keys without a callback (memory store only)", function() {
var keys = cache.keys();
assert.deepEqual(keys.sort, saved_keys.sort);
assert.deepEqual(keys.sort, savedKeys.sort);
});
});
describe("wrap()", function() {
describe("using memory (lru-cache) store", function() {
var memory_store_stub;
var memoryStoreStub;
beforeEach(function() {
ttl = 0.1;
memory_store_stub = memory_store.create({ttl: ttl});
memoryStoreStub = memoryStore.create({ttl: ttl});
sinon.stub(memory_store, 'create').returns(memory_store_stub);
sinon.stub(memoryStore, 'create').returns(memoryStoreStub);
cache = caching({store: 'memory', ttl: ttl, ignoreCacheErrors: false});
key = support.random.string(20);
@ -247,58 +247,58 @@ describe("caching", function() {
});
afterEach(function() {
memory_store.create.restore();
memoryStore.create.restore();
});
context("calls back with the result of the wrapped function", function() {
beforeEach(function() {
sinon.spy(memory_store_stub, 'set');
sinon.spy(memoryStoreStub, 'set');
});
afterEach(function() {
memory_store_stub.set.restore();
memoryStoreStub.set.restore();
});
it("when a ttl is passed in", function(done) {
cache.wrap(key, function(cb) {
methods.get_widget(name, cb);
methods.getWidget(name, cb);
}, ttl, function(err, widget) {
check_err(err);
checkErr(err);
assert.deepEqual(widget, {name: name});
sinon.assert.calledWith(memory_store_stub.set, key, {name: name}, ttl);
sinon.assert.calledWith(memoryStoreStub.set, key, {name: name}, ttl);
done();
});
});
it("when a ttl is not passed in", function(done) {
cache.wrap(key, function(cb) {
methods.get_widget(name, cb);
methods.getWidget(name, cb);
}, function(err, widget) {
check_err(err);
checkErr(err);
assert.deepEqual(widget, {name: name});
sinon.assert.calledWith(memory_store_stub.set, key, {name: name}, undefined);
sinon.assert.calledWith(memoryStoreStub.set, key, {name: name}, undefined);
done();
});
});
});
context("when result is already cached", function() {
function get_cached_widget(name, cb) {
cache.wrap(key, function(cache_cb) {
methods.get_widget(name, cache_cb);
function getCachedWidget(name, cb) {
cache.wrap(key, function(cacheCb) {
methods.getWidget(name, cacheCb);
}, ttl, cb);
}
beforeEach(function(done) {
get_cached_widget(name, function(err, widget) {
check_err(err);
getCachedWidget(name, function(err, widget) {
checkErr(err);
assert.ok(widget);
memory_store_stub.get(key, function(err, result) {
check_err(err);
memoryStoreStub.get(key, function(err, result) {
checkErr(err);
assert.ok(result);
sinon.spy(memory_store_stub, 'get');
sinon.spy(memoryStoreStub, 'get');
done();
});
@ -306,44 +306,44 @@ describe("caching", function() {
});
afterEach(function() {
memory_store_stub.get.restore();
memoryStoreStub.get.restore();
});
it("retrieves data from cache", function(done) {
var func_called = false;
var funcCalled = false;
cache.wrap(key, function(cb) {
methods.get_widget(name, function(err, result) {
func_called = true;
methods.getWidget(name, function(err, result) {
funcCalled = true;
cb(err, result);
});
}, ttl, function(err, widget) {
check_err(err);
checkErr(err);
assert.deepEqual(widget, {name: name});
assert.ok(memory_store_stub.get.calledWith(key));
assert.ok(!func_called);
assert.ok(memoryStoreStub.get.calledWith(key));
assert.ok(!funcCalled);
done();
});
});
});
it("lets us make nested calls", function(done) {
function get_cached_widget(name, cb) {
cache.wrap(key, function(cache_cb) {
methods.get_widget(name, cache_cb);
function getCachedWidget(name, cb) {
cache.wrap(key, function(cacheCb) {
methods.getWidget(name, cacheCb);
}, cb);
}
get_cached_widget(name, function(err, widget) {
check_err(err);
getCachedWidget(name, function(err, widget) {
checkErr(err);
assert.equal(widget.name, name);
get_cached_widget(name, function(err, widget) {
check_err(err);
getCachedWidget(name, function(err, widget) {
checkErr(err);
assert.equal(widget.name, name);
get_cached_widget(name, function(err, widget) {
check_err(err);
getCachedWidget(name, function(err, widget) {
checkErr(err);
assert.equal(widget.name, name);
done();
});
@ -353,26 +353,26 @@ describe("caching", function() {
it("expires cached result after ttl seconds", function(done) {
cache.wrap(key, function(cb) {
methods.get_widget(name, cb);
methods.getWidget(name, cb);
}, ttl, function(err, widget) {
check_err(err);
checkErr(err);
assert.deepEqual(widget, {name: name});
memory_store_stub.get(key, function(err, result) {
check_err(err);
memoryStoreStub.get(key, function(err, result) {
checkErr(err);
assert.ok(result);
var func_called = false;
var funcCalled = false;
setTimeout(function() {
cache.wrap(key, function(cb) {
methods.get_widget(name, function(err, result) {
func_called = true;
methods.getWidget(name, function(err, result) {
funcCalled = true;
cb(err, result);
});
}, function(err, widget) {
check_err(err);
assert.ok(func_called);
checkErr(err);
assert.ok(funcCalled);
assert.deepEqual(widget, {name: name});
done();
});
@ -382,17 +382,17 @@ describe("caching", function() {
});
context("when an error is thrown in the work function", function() {
var fake_error;
var fakeError;
beforeEach(function() {
fake_error = new Error(support.random.string());
fakeError = new Error(support.random.string());
});
it("bubbles up that error", function(done) {
cache.wrap(key, function() {
throw fake_error;
throw fakeError;
}, ttl, function(err) {
assert.equal(err, fake_error);
assert.equal(err, fakeError);
done();
});
});
@ -401,17 +401,17 @@ describe("caching", function() {
context("when store.get() calls back with an error", function() {
context("and ignoreCacheErrors is not set (default is false)", function() {
it("bubbles up that error", function(done) {
var fake_error = new Error(support.random.string());
var fakeError = new Error(support.random.string());
sinon.stub(memory_store_stub, 'get', function(key, options, cb) {
cb(fake_error);
sinon.stub(memoryStoreStub, 'get', function(key, options, cb) {
cb(fakeError);
});
cache.wrap(key, function(cb) {
methods.get_widget(name, cb);
methods.getWidget(name, cb);
}, ttl, function(err) {
assert.equal(err, fake_error);
memory_store_stub.get.restore();
assert.equal(err, fakeError);
memoryStoreStub.get.restore();
done();
});
});
@ -421,17 +421,17 @@ describe("caching", function() {
it("does not bubble up that error", function(done) {
cache = caching({store: 'memory', ttl: ttl, ignoreCacheErrors: true});
var fake_error = new Error(support.random.string());
var fakeError = new Error(support.random.string());
sinon.stub(memory_store_stub, 'get', function(key, options, cb) {
cb(fake_error);
sinon.stub(memoryStoreStub, 'get', function(key, options, cb) {
cb(fakeError);
});
cache.wrap(key, function(cb) {
methods.get_widget(name, cb);
methods.getWidget(name, cb);
}, ttl, function(err) {
assert.equal(err, null);
memory_store_stub.get.restore();
memoryStoreStub.get.restore();
done();
});
});
@ -441,17 +441,17 @@ describe("caching", function() {
context("when store.set() calls back with an error", function() {
context("and ignoreCacheErrors is not set", function() {
it("bubbles up that error", function(done) {
var fake_error = new Error(support.random.string());
var fakeError = new Error(support.random.string());
sinon.stub(memory_store_stub, 'set', function(key, val, ttl, cb) {
cb(fake_error);
sinon.stub(memoryStoreStub, 'set', function(key, val, ttl, cb) {
cb(fakeError);
});
cache.wrap(key, function(cb) {
methods.get_widget(name, cb);
methods.getWidget(name, cb);
}, ttl, function(err) {
assert.equal(err, fake_error);
memory_store_stub.set.restore();
assert.equal(err, fakeError);
memoryStoreStub.set.restore();
done();
});
});
@ -460,17 +460,17 @@ describe("caching", function() {
context("and ignoreCacheErrors is set to true", function() {
it("does not bubbles up that error", function(done) {
cache = caching({store: 'memory', ttl: ttl, ignoreCacheErrors: true});
var fake_error = new Error(support.random.string());
var fakeError = new Error(support.random.string());
sinon.stub(memory_store_stub, 'set', function(key, val, ttl, cb) {
cb(fake_error);
sinon.stub(memoryStoreStub, 'set', function(key, val, ttl, cb) {
cb(fakeError);
});
cache.wrap(key, function(cb) {
methods.get_widget(name, cb);
methods.getWidget(name, cb);
}, ttl, function(err) {
assert.equal(err, null);
memory_store_stub.set.restore();
memoryStoreStub.set.restore();
done();
});
});
@ -479,16 +479,16 @@ describe("caching", function() {
context("when wrapped function calls back with an error", function() {
it("calls back with that error", function(done) {
var fake_error = new Error(support.random.string());
sinon.stub(methods, 'get_widget', function(name, cb) {
cb(fake_error, {name: name});
var fakeError = new Error(support.random.string());
sinon.stub(methods, 'getWidget', function(name, cb) {
cb(fakeError, {name: name});
});
cache.wrap(key, function(cb) {
methods.get_widget(name, cb);
methods.getWidget(name, cb);
}, ttl, function(err, widget) {
methods.get_widget.restore();
assert.equal(err, fake_error);
methods.getWidget.restore();
assert.equal(err, fakeError);
assert.ok(!widget);
done();
});
@ -520,15 +520,15 @@ describe("caching", function() {
values.push(i);
}
async.each(values, function(val, async_cb) {
async.each(values, function(val, next) {
cache.wrap('key', function(cb) {
construct(val, cb);
}, ttl, function(err, result) {
assert.equal(result, 'value');
async_cb(err);
next(err);
});
}, function(err) {
check_err(err);
checkErr(err);
assert.equal(construct.callCount, 1);
done();
});
@ -545,10 +545,10 @@ describe("caching", function() {
describe("instantiating with custom store", function() {
it("allows us to pass in our own store object", function(done) {
var store = memory_store.create({ttl: ttl});
var store = memoryStore.create({ttl: ttl});
cache = caching({store: store});
cache.set(key, value, ttl, function(err) {
check_err(err);
checkErr(err);
cache.get(key, function(err, result) {
assert.equal(result, value);
done();
@ -557,10 +557,10 @@ describe("caching", function() {
});
it("allows us to pass in a path to our own store", function(done) {
var store_path = '../lib/stores/memory';
cache = caching({store: store_path});
var storePath = '../lib/stores/memory';
cache = caching({store: storePath});
cache.set(key, value, ttl, function(err) {
check_err(err);
checkErr(err);
cache.get(key, function(err, result) {
assert.equal(result, value);
done();
@ -569,10 +569,10 @@ describe("caching", function() {
});
it("allows us to pass in a module (uninstantiated)", function(done) {
var store = memory_store;
var store = memoryStore;
cache = caching({store: store});
cache.set(key, value, ttl, function(err) {
check_err(err);
checkErr(err);
cache.get(key, function(err, result) {
assert.equal(result, value);
done();

410
test/multi_caching.unit.js

@ -2,33 +2,33 @@ var assert = require('assert');
var async = require('async');
var sinon = require('sinon');
var support = require('./support');
var check_err = support.check_err;
var checkErr = support.checkErr;
var caching = require('../index').caching;
var multi_caching = require('../index').multi_caching;
var memory_store = require('../lib/stores/memory');
var multiCaching = require('../index').multiCaching;
var memoryStore = require('../lib/stores/memory');
var methods = {
get_widget: function(name, cb) {
getWidget: function(name, cb) {
cb(null, {name: name});
}
};
describe("multi_caching", function() {
var memory_cache;
var memory_cache2;
var memory_cache3;
var multi_cache;
describe("multiCaching", function() {
var memoryCache;
var memoryCache2;
var memoryCache3;
var multiCache;
var key;
var memory_ttl;
var memoryTtl;
var name;
var ttl = 5;
beforeEach(function() {
memory_ttl = 0.1;
memoryTtl = 0.1;
memory_cache = caching({store: 'memory', ttl: memory_ttl});
memory_cache2 = caching({store: 'memory', ttl: memory_ttl});
memory_cache3 = caching({store: 'memory', ttl: memory_ttl});
memoryCache = caching({store: 'memory', ttl: memoryTtl});
memoryCache2 = caching({store: 'memory', ttl: memoryTtl});
memoryCache3 = caching({store: 'memory', ttl: memoryTtl});
key = support.random.string(20);
name = support.random.string();
@ -38,24 +38,24 @@ describe("multi_caching", function() {
var value;
beforeEach(function() {
multi_cache = multi_caching([memory_cache, memory_cache2, memory_cache3]);
multiCache = multiCaching([memoryCache, memoryCache2, memoryCache3]);
key = support.random.string(20);
value = support.random.string();
});
describe("set()", function() {
it("lets us set data in all caches", function(done) {
multi_cache.set(key, value, ttl, function(err) {
check_err(err);
memory_cache.get(key, function(err, result) {
multiCache.set(key, value, ttl, function(err) {
checkErr(err);
memoryCache.get(key, function(err, result) {
assert.equal(result, value);
memory_cache2.get(key, function(err, result) {
check_err(err);
memoryCache2.get(key, function(err, result) {
checkErr(err);
assert.equal(result, value);
memory_cache3.get(key, function(err, result) {
check_err(err);
memoryCache3.get(key, function(err, result) {
checkErr(err);
assert.equal(result, value);
done();
});
@ -65,19 +65,19 @@ describe("multi_caching", function() {
});
it("lets us set data without a callback", function(done) {
multi_cache.set(key, value, ttl);
multiCache.set(key, value, ttl);
setTimeout(function() {
multi_cache.get(key, function(err, result) {
multiCache.get(key, function(err, result) {
assert.equal(result, value);
memory_cache.get(key, function(err, result) {
memoryCache.get(key, function(err, result) {
assert.equal(result, value);
memory_cache2.get(key, function(err, result) {
check_err(err);
memoryCache2.get(key, function(err, result) {
checkErr(err);
assert.equal(result, value);
memory_cache3.get(key, function(err, result) {
check_err(err);
memoryCache3.get(key, function(err, result) {
checkErr(err);
assert.equal(result, value);
done();
});
@ -88,19 +88,19 @@ describe("multi_caching", function() {
});
it("lets us set data without a ttl or callback", function(done) {
multi_cache.set(key, value);
multiCache.set(key, value);
setTimeout(function() {
multi_cache.get(key, function(err, result) {
multiCache.get(key, function(err, result) {
assert.equal(result, value);
memory_cache.get(key, function(err, result) {
memoryCache.get(key, function(err, result) {
assert.equal(result, value);
memory_cache2.get(key, function(err, result) {
check_err(err);
memoryCache2.get(key, function(err, result) {
checkErr(err);
assert.equal(result, value);
memory_cache3.get(key, function(err, result) {
check_err(err);
memoryCache3.get(key, function(err, result) {
checkErr(err);
assert.equal(result, value);
done();
});
@ -113,11 +113,11 @@ describe("multi_caching", function() {
describe("get()", function() {
it("gets data from first cache that has it", function(done) {
memory_cache3.set(key, value, ttl, function(err) {
check_err(err);
memoryCache3.set(key, value, ttl, function(err) {
checkErr(err);
multi_cache.get(key, function(err, result) {
check_err(err);
multiCache.get(key, function(err, result) {
checkErr(err);
assert.equal(result, value);
done();
});
@ -127,21 +127,21 @@ describe("multi_caching", function() {
describe("del()", function() {
it("lets us delete data in all caches", function(done) {
multi_cache.set(key, value, ttl, function(err) {
check_err(err);
multiCache.set(key, value, ttl, function(err) {
checkErr(err);
multi_cache.del(key, function(err) {
check_err(err);
multiCache.del(key, function(err) {
checkErr(err);
memory_cache.get(key, function(err, result) {
memoryCache.get(key, function(err, result) {
assert.ok(!result);
memory_cache2.get(key, function(err, result) {
check_err(err);
memoryCache2.get(key, function(err, result) {
checkErr(err);
assert.ok(!result);
memory_cache3.get(key, function(err, result) {
check_err(err);
memoryCache3.get(key, function(err, result) {
checkErr(err);
assert.ok(!result);
done();
});
@ -152,21 +152,21 @@ describe("multi_caching", function() {
});
it("lets us delete data without a callback", function(done) {
multi_cache.set(key, value, ttl, function(err) {
check_err(err);
multiCache.set(key, value, ttl, function(err) {
checkErr(err);
multi_cache.del(key);
multiCache.del(key);
setTimeout(function() {
memory_cache.get(key, function(err, result) {
memoryCache.get(key, function(err, result) {
assert.ok(!result);
memory_cache2.get(key, function(err, result) {
check_err(err);
memoryCache2.get(key, function(err, result) {
checkErr(err);
assert.ok(!result);
memory_cache3.get(key, function(err, result) {
check_err(err);
memoryCache3.get(key, function(err, result) {
checkErr(err);
assert.ok(!result);
done();
});
@ -178,23 +178,23 @@ describe("multi_caching", function() {
});
});
describe("get_and_pass_up()", function() {
describe("getAndPassUp()", function() {
var value;
var key;
describe("using a single cache store", function() {
beforeEach(function() {
multi_cache = multi_caching([memory_cache3]);
multiCache = multiCaching([memoryCache3]);
key = support.random.string(20);
value = support.random.string();
});
it("gets data from first cache that has it", function(done) {
memory_cache3.set(key, value, ttl, function(err) {
check_err(err);
memoryCache3.set(key, value, ttl, function(err) {
checkErr(err);
multi_cache.get_and_pass_up(key, function(err, result) {
check_err(err);
multiCache.getAndPassUp(key, function(err, result) {
checkErr(err);
assert.equal(result, value);
done();
});
@ -207,21 +207,21 @@ describe("multi_caching", function() {
beforeEach(function(done) {
key = support.random.string(10);
sinon.spy(memory_cache, 'set');
sinon.spy(memory_cache2, 'set');
sinon.spy(memory_cache3, 'set');
sinon.spy(memoryCache, 'set');
sinon.spy(memoryCache2, 'set');
sinon.spy(memoryCache3, 'set');
multi_cache.get_and_pass_up(key, function(err, result) {
check_err(err);
multiCache.getAndPassUp(key, function(err, result) {
checkErr(err);
response = result;
done();
});
});
afterEach(function() {
memory_cache.set.restore();
memory_cache2.set.restore();
memory_cache3.set.restore();
memoryCache.set.restore();
memoryCache2.set.restore();
memoryCache3.set.restore();
});
it("calls back with undefined", function() {
@ -230,9 +230,9 @@ describe("multi_caching", function() {
it("does not set anything in caches", function(done) {
process.nextTick(function() {
assert.ok(memory_cache.set.notCalled);
assert.ok(memory_cache2.set.notCalled);
assert.ok(memory_cache3.set.notCalled);
assert.ok(memoryCache.set.notCalled);
assert.ok(memoryCache2.set.notCalled);
assert.ok(memoryCache3.set.notCalled);
done();
});
});
@ -240,23 +240,23 @@ describe("multi_caching", function() {
describe("using multi cache store", function() {
beforeEach(function() {
multi_cache = multi_caching([memory_cache, memory_cache2, memory_cache3]);
multiCache = multiCaching([memoryCache, memoryCache2, memoryCache3]);
key = support.random.string(20);
value = support.random.string();
});
it("checks to see if higher levels have item", function(done) {
memory_cache3.set(key, value, ttl, function(err) {
check_err(err);
memoryCache3.set(key, value, ttl, function(err) {
checkErr(err);
multi_cache.get_and_pass_up(key, function(err, result) {
check_err(err);
multiCache.getAndPassUp(key, function(err, result) {
checkErr(err);
assert.equal(result, value);
process.nextTick(function() {
memory_cache.get(key, function(err, result) {
memoryCache.get(key, function(err, result) {
assert.equal(result, value);
check_err(err);
checkErr(err);
done();
});
});
@ -269,36 +269,36 @@ describe("multi_caching", function() {
describe("wrap()", function() {
describe("using a single cache store", function() {
beforeEach(function() {
multi_cache = multi_caching([memory_cache3]);
multiCache = multiCaching([memoryCache3]);
});
context("calls back with the result of a function", function() {
beforeEach(function() {
sinon.spy(memory_cache3.store, 'set');
sinon.spy(memoryCache3.store, 'set');
});
afterEach(function() {
memory_cache3.store.set.restore();
memoryCache3.store.set.restore();
});
it('when a ttl is passed in', function(done) {
multi_cache.wrap(key, function(cb) {
methods.get_widget(name, cb);
multiCache.wrap(key, function(cb) {
methods.getWidget(name, cb);
}, ttl, function(err, widget) {
check_err(err);
checkErr(err);
assert.deepEqual(widget, {name: name});
sinon.assert.calledWith(memory_cache3.store.set, key, {name: name}, ttl);
sinon.assert.calledWith(memoryCache3.store.set, key, {name: name}, ttl);
done();
});
});
it('when a ttl is not passed in', function(done) {
multi_cache.wrap(key, function(cb) {
methods.get_widget(name, cb);
multiCache.wrap(key, function(cb) {
methods.getWidget(name, cb);
}, function(err, widget) {
check_err(err);
checkErr(err);
assert.deepEqual(widget, {name: name});
sinon.assert.calledWith(memory_cache3.store.set, key, {name: name});
sinon.assert.calledWith(memoryCache3.store.set, key, {name: name});
done();
});
});
@ -306,16 +306,16 @@ describe("multi_caching", function() {
context("when wrapped function calls back with an error", function() {
it("calls back with that error", function(done) {
var fake_error = new Error(support.random.string());
sinon.stub(methods, 'get_widget', function(name, cb) {
cb(fake_error, {name: name});
var fakeError = new Error(support.random.string());
sinon.stub(methods, 'getWidget', function(name, cb) {
cb(fakeError, {name: name});
});
multi_cache.wrap(key, function(cb) {
methods.get_widget(name, cb);
multiCache.wrap(key, function(cb) {
methods.getWidget(name, cb);
}, function(err, widget) {
methods.get_widget.restore();
assert.equal(err, fake_error);
methods.getWidget.restore();
assert.equal(err, fakeError);
assert.ok(!widget);
done();
});
@ -325,32 +325,32 @@ describe("multi_caching", function() {
describe("using two cache stores", function() {
beforeEach(function() {
multi_cache = multi_caching([memory_cache, memory_cache3]);
multiCache = multiCaching([memoryCache, memoryCache3]);
});
it("calls back with the result of a function", function(done) {
multi_cache.wrap(key, function(cb) {
methods.get_widget(name, cb);
multiCache.wrap(key, function(cb) {
methods.getWidget(name, cb);
}, function(err, widget) {
check_err(err);
checkErr(err);
assert.deepEqual(widget, {name: name});
done();
});
});
it("sets value in all caches", function(done) {
multi_cache.wrap(key, function(cb) {
methods.get_widget(name, cb);
multiCache.wrap(key, function(cb) {
methods.getWidget(name, cb);
}, function(err, widget) {
check_err(err);
checkErr(err);
assert.deepEqual(widget, {name: name});
memory_cache.get(key, function(err, result) {
check_err(err);
memoryCache.get(key, function(err, result) {
checkErr(err);
assert.deepEqual(result, {name: name});
memory_cache3.get(key, function(err, result) {
check_err(err);
memoryCache3.get(key, function(err, result) {
checkErr(err);
assert.deepEqual(result, {name: name});
done();
});
@ -360,17 +360,17 @@ describe("multi_caching", function() {
context("when value exists in first store but not second", function() {
it("returns value from first store, does not set it in second", function(done) {
memory_cache.set(key, {name: name}, ttl, function(err) {
check_err(err);
memoryCache.set(key, {name: name}, ttl, function(err) {
checkErr(err);
multi_cache.wrap(key, function(cb) {
methods.get_widget(name, cb);
multiCache.wrap(key, function(cb) {
methods.getWidget(name, cb);
}, function(err, widget) {
check_err(err);
checkErr(err);
assert.deepEqual(widget, {name: name});
memory_cache3.get(key, function(err, result) {
check_err(err);
memoryCache3.get(key, function(err, result) {
checkErr(err);
assert.equal(result, null);
done();
});
@ -381,17 +381,17 @@ describe("multi_caching", function() {
context("when value exists in second store but not first", function() {
it("returns value from second store, sets it in first store", function(done) {
memory_cache3.set(key, {name: name}, ttl, function(err) {
check_err(err);
memoryCache3.set(key, {name: name}, ttl, function(err) {
checkErr(err);
multi_cache.wrap(key, function(cb) {
methods.get_widget(name, cb);
multiCache.wrap(key, function(cb) {
methods.getWidget(name, cb);
}, function(err, widget) {
check_err(err);
checkErr(err);
assert.deepEqual(widget, {name: name});
memory_cache.get(key, function(err, result) {
check_err(err);
memoryCache.get(key, function(err, result) {
checkErr(err);
assert.deepEqual(result, {name: name});
done();
});
@ -403,36 +403,36 @@ describe("multi_caching", function() {
describe("using three cache stores", function() {
beforeEach(function() {
multi_cache = multi_caching([memory_cache, memory_cache3, memory_cache2]);
multiCache = multiCaching([memoryCache, memoryCache3, memoryCache2]);
});
it("calls back with the result of a function", function(done) {
multi_cache.wrap(key, function(cb) {
methods.get_widget(name, cb);
multiCache.wrap(key, function(cb) {
methods.getWidget(name, cb);
}, function(err, widget) {
check_err(err);
checkErr(err);
assert.deepEqual(widget, {name: name});
done();
});
});
it("sets value in all caches", function(done) {
multi_cache.wrap(key, function(cb) {
methods.get_widget(name, cb);
multiCache.wrap(key, function(cb) {
methods.getWidget(name, cb);
}, function(err, widget) {
check_err(err);
checkErr(err);
assert.deepEqual(widget, {name: name});
memory_cache.get(key, function(err, result) {
check_err(err);
memoryCache.get(key, function(err, result) {
checkErr(err);
assert.deepEqual(result, {name: name});
memory_cache2.get(key, function(err, result) {
check_err(err);
memoryCache2.get(key, function(err, result) {
checkErr(err);
assert.deepEqual(result, {name: name});
memory_cache3.get(key, function(err, result) {
check_err(err);
memoryCache3.get(key, function(err, result) {
checkErr(err);
assert.deepEqual(result, {name: name});
done();
});
@ -443,21 +443,21 @@ describe("multi_caching", function() {
context("when value exists in first store only", function() {
it("returns value from first store, does not set it in second or third", function(done) {
memory_cache.set(key, {name: name}, ttl, function(err) {
check_err(err);
memoryCache.set(key, {name: name}, ttl, function(err) {
checkErr(err);
multi_cache.wrap(key, function(cb) {
methods.get_widget(name, cb);
multiCache.wrap(key, function(cb) {
methods.getWidget(name, cb);
}, function(err, widget) {
check_err(err);
checkErr(err);
assert.deepEqual(widget, {name: name});
memory_cache2.get(key, function(err, result) {
check_err(err);
memoryCache2.get(key, function(err, result) {
checkErr(err);
assert.equal(result, null);
memory_cache3.get(key, function(err, result) {
check_err(err);
memoryCache3.get(key, function(err, result) {
checkErr(err);
assert.equal(result, null);
done();
});
@ -469,21 +469,21 @@ describe("multi_caching", function() {
context("when value exists in second store only", function() {
it("returns value from second store, sets it in first store, does not set third store", function(done) {
memory_cache3.set(key, {name: name}, ttl, function(err) {
check_err(err);
memoryCache3.set(key, {name: name}, ttl, function(err) {
checkErr(err);
multi_cache.wrap(key, function(cb) {
methods.get_widget(name, cb);
multiCache.wrap(key, function(cb) {
methods.getWidget(name, cb);
}, function(err, widget) {
check_err(err);
checkErr(err);
assert.deepEqual(widget, {name: name});
memory_cache.get(key, function(err, result) {
check_err(err);
memoryCache.get(key, function(err, result) {
checkErr(err);
assert.deepEqual(result, {name: name});
memory_cache2.get(key, function(err, result) {
check_err(err);
memoryCache2.get(key, function(err, result) {
checkErr(err);
assert.equal(result, null);
done();
});
@ -495,21 +495,21 @@ describe("multi_caching", function() {
context("when value exists in third store only", function() {
it("returns value from third store, sets it in first and second stores", function(done) {
memory_cache2.set(key, {name: name}, ttl, function(err) {
check_err(err);
memoryCache2.set(key, {name: name}, ttl, function(err) {
checkErr(err);
multi_cache.wrap(key, function(cb) {
methods.get_widget(name, cb);
multiCache.wrap(key, function(cb) {
methods.getWidget(name, cb);
}, function(err, widget) {
check_err(err);
checkErr(err);
assert.deepEqual(widget, {name: name});
memory_cache3.get(key, function(err, result) {
check_err(err);
memoryCache3.get(key, function(err, result) {
checkErr(err);
assert.deepEqual(result, {name: name});
memory_cache.get(key, function(err, result) {
check_err(err);
memoryCache.get(key, function(err, result) {
checkErr(err);
assert.deepEqual(result, {name: name});
done();
@ -521,22 +521,22 @@ describe("multi_caching", function() {
});
it("lets us make nested calls", function(done) {
function get_cached_widget(name, cb) {
multi_cache.wrap(key, function(cache_cb) {
methods.get_widget(name, cache_cb);
function getCachedWidget(name, cb) {
multiCache.wrap(key, function(cacheCb) {
methods.getWidget(name, cacheCb);
}, cb);
}
get_cached_widget(name, function(err, widget) {
check_err(err);
getCachedWidget(name, function(err, widget) {
checkErr(err);
assert.equal(widget.name, name);
get_cached_widget(name, function(err, widget) {
check_err(err);
getCachedWidget(name, function(err, widget) {
checkErr(err);
assert.equal(widget.name, name);
get_cached_widget(name, function(err, widget) {
check_err(err);
getCachedWidget(name, function(err, widget) {
checkErr(err);
assert.equal(widget.name, name);
done();
});
@ -546,33 +546,33 @@ describe("multi_caching", function() {
});
context("error handling", function() {
var memory_store_stub;
var memoryStoreStub;
var ttl;
beforeEach(function() {
ttl = 0.1;
memory_store_stub = memory_store.create({ttl: ttl});
sinon.stub(memory_store, 'create').returns(memory_store_stub);
memory_cache = caching({store: 'memory', ttl: ttl});
multi_cache = multi_caching([memory_cache]);
memoryStoreStub = memoryStore.create({ttl: ttl});
sinon.stub(memoryStore, 'create').returns(memoryStoreStub);
memoryCache = caching({store: 'memory', ttl: ttl});
multiCache = multiCaching([memoryCache]);
});
afterEach(function() {
memory_store.create.restore();
memoryStore.create.restore();
});
context("when an error is thrown in the work function", function() {
var fake_error;
var fakeError;
beforeEach(function() {
fake_error = new Error(support.random.string());
fakeError = new Error(support.random.string());
});
it("bubbles up that error", function(done) {
multi_cache.wrap(key, function() {
throw fake_error;
multiCache.wrap(key, function() {
throw fakeError;
}, ttl, function(err) {
assert.equal(err, fake_error);
assert.equal(err, fakeError);
done();
});
});
@ -580,17 +580,17 @@ describe("multi_caching", function() {
context("when store.get() calls back with an error", function() {
it("bubbles up that error", function(done) {
var fake_error = new Error(support.random.string());
var fakeError = new Error(support.random.string());
sinon.stub(memory_store_stub, 'get', function(key, cb) {
cb(fake_error);
sinon.stub(memoryStoreStub, 'get', function(key, cb) {
cb(fakeError);
});
multi_cache.wrap(key, function(cb) {
methods.get_widget(name, cb);
multiCache.wrap(key, function(cb) {
methods.getWidget(name, cb);
}, function(err) {
assert.equal(err, fake_error);
memory_store_stub.get.restore();
assert.equal(err, fakeError);
memoryStoreStub.get.restore();
done();
});
});
@ -598,17 +598,17 @@ describe("multi_caching", function() {
context("when store.set() calls back with an error", function() {
it("bubbles up that error", function(done) {
var fake_error = new Error(support.random.string());
var fakeError = new Error(support.random.string());
sinon.stub(memory_store_stub, 'set', function(key, val, ttl, cb) {
cb(fake_error);
sinon.stub(memoryStoreStub, 'set', function(key, val, ttl, cb) {
cb(fakeError);
});
multi_cache.wrap(key, function(cb) {
methods.get_widget(name, cb);
multiCache.wrap(key, function(cb) {
methods.getWidget(name, cb);
}, function(err) {
assert.equal(err, fake_error);
memory_store_stub.set.restore();
assert.equal(err, fakeError);
memoryStoreStub.set.restore();
done();
});
});
@ -619,7 +619,7 @@ describe("multi_caching", function() {
var construct;
beforeEach(function() {
multi_cache = multi_caching([memory_cache, memory_cache3]);
multiCache = multiCaching([memoryCache, memoryCache3]);
construct = sinon.spy(function(val, cb) {
var timeout = support.random.number(100);
@ -635,15 +635,15 @@ describe("multi_caching", function() {
values.push(i);
}
async.each(values, function(val, async_cb) {
multi_cache.wrap('key', function(cb) {
async.each(values, function(val, next) {
multiCache.wrap('key', function(cb) {
construct(val, cb);
}, function(err, result) {
assert.equal(result, 'value');
async_cb(err);
next(err);
});
}, function(err) {
check_err(err);
checkErr(err);
assert.equal(construct.callCount, 1);
done();
});
@ -654,8 +654,8 @@ describe("multi_caching", function() {
context("when instantiated with a non-Array 'caches' arg", function() {
it("throws an error", function() {
assert.throws(function() {
multi_caching({foo: 'bar'});
}, /multi_caching requires an array/);
multiCaching({foo: 'bar'});
}, /multiCaching requires an array/);
});
});
});

26
test/run.js

@ -4,7 +4,7 @@ require('../index');
var Mocha = require('mocha');
var optimist = require('optimist');
var walk_dir = require('./support').walk_dir;
var walkDir = require('./support').walkDir;
var argv = optimist
.usage("Usage: $0 -t [types] --reporter [reporter] --timeout [timeout]")['default'](
@ -21,29 +21,29 @@ var argv = optimist
var mocha = new Mocha({timeout: argv.timeout, reporter: argv.reporter, ui: 'bdd'});
var valid_test_types = ['unit', 'functional', 'acceptance', 'integration'];
var requested_types = argv.types.split(',');
var types_to_use = [];
var validTestTypes = ['unit', 'functional', 'acceptance', 'integration'];
var requestedTypes = argv.types.split(',');
var typesToUse = [];
valid_test_types.forEach(function(valid_test_type) {
if (requested_types.indexOf(valid_test_type) !== -1) {
types_to_use.push(valid_test_type);
validTestTypes.forEach(function(validTestType) {
if (requestedTypes.indexOf(validTestType) !== -1) {
typesToUse.push(validTestType);
}
});
if (argv.help || types_to_use.length === 0) {
if (argv.help || typesToUse.length === 0) {
console.log('\n' + optimist.help());
process.exit();
}
var is_valid_file = function(file) {
var isValidFile = function(file) {
if (file.match(/buster/)) {
return false;
}
for (var i = 0; i < types_to_use.length; i++) {
var test_type = types_to_use[i];
var ext = test_type + ".js";
for (var i = 0; i < typesToUse.length; i++) {
var testType = typesToUse[i];
var ext = testType + ".js";
if (file.indexOf(ext) !== -1) {
return true;
@ -54,7 +54,7 @@ var is_valid_file = function(file) {
};
function run(cb) {
walk_dir('test', is_valid_file, function(err, files) {
walkDir('test', isValidFile, function(err, files) {
if (err) { return cb(err); }
files.forEach(function(file) {

6
test/stores/memory.unit.js

@ -1,11 +1,11 @@
var support = require('../support');
var memory_store = require('../../lib/stores/memory');
var memoryStore = require('../../lib/stores/memory');
describe("memory store", function() {
describe("instantiating", function() {
it("lets us pass in no args", function(done) {
var memory_cache = memory_store.create();
support.test_set_get_del(memory_cache, done);
var memoryCache = memoryStore.create();
support.testSetGetDel(memoryCache, done);
});
});
});

22
test/stores/options.unit.js

@ -1,7 +1,7 @@
var caching = require("../../index");
var assert = require("assert");
var support = require("../support");
var check_err = support.check_err;
var checkErr = support.checkErr;
var memoryFlag = "";
var key;
var value;
@ -91,7 +91,7 @@ describe("Methods with options", function() {
before(function() {
key = support.random.string(20);
value = support.random.string(20);
testCache = caching.multi_caching([testInstance]);
testCache = caching.multiCaching([testInstance]);
});
describe("get with options", function() {
@ -170,19 +170,19 @@ describe("Multiple stores with options", function() {
before(function() {
key = support.random.string(20);
value = support.random.string(20);
testCache = caching.multi_caching([testInstance, memInstance]);
testCache = caching.multiCaching([testInstance, memInstance]);
});
it("lets us pass options which only one store uses", function() {
testCache.set(key, value, options, function(err) {
check_err(err);
checkErr(err);
testCache.get(key, options, function(err, response) {
check_err(err);
checkErr(err);
assert.equal(response, value);
testCache.del(key, options, function(err) {
check_err(err);
checkErr(err);
testCache.get(key, options, function(err, response) {
check_err(err);
checkErr(err);
assert.equal(response, undefined);
});
});
@ -192,14 +192,14 @@ describe("Multiple stores with options", function() {
it("lets us not pass options which only one store uses", function() {
testCache.set(key, value, ttl, function(err) {
check_err(err);
checkErr(err);
testCache.get(key, function(err, response) {
check_err(err);
checkErr(err);
assert.equal(response, value);
testCache.del(key, function(err) {
check_err(err);
checkErr(err);
testCache.get(key, function(err, response) {
check_err(err);
checkErr(err);
assert.equal(response, undefined);
});
});

34
test/support.js

@ -4,15 +4,15 @@ var assert = require('assert');
var support = {
random: {
string: function(str_len) {
str_len = str_len || 8;
string: function(strLen) {
strLen = strLen || 8;
var chars = "abcdefghiklmnopqrstuvwxyz";
var random_str = '';
for (var i = 0; i < str_len; i++) {
var randomStr = '';
for (var i = 0; i < strLen; i++) {
var rnum = Math.floor(Math.random() * chars.length);
random_str += chars.substring(rnum, rnum + 1);
randomStr += chars.substring(rnum, rnum + 1);
}
return random_str;
return randomStr;
},
number: function(max) {
@ -21,7 +21,7 @@ var support = {
}
},
check_err: function(err) {
checkErr: function(err) {
if (err) {
var msg;
@ -38,21 +38,21 @@ var support = {
}
},
assert_between: function(actual, lower, upper) {
assertBetween: function(actual, lower, upper) {
assert.ok(actual >= lower, "Expected " + actual + " to be >= " + lower);
assert.ok(actual <= upper, "Expected " + actual + " to be <= " + upper);
},
assert_within: function(actual, expected, delta) {
assertWithin: function(actual, expected, delta) {
var lower = expected - delta;
var upper = expected + delta;
this.assert_between(actual, lower, upper);
this.assertBetween(actual, lower, upper);
},
walk_dir: function(dir, validation_function, cb) {
walkDir: function(dir, validationFunction, cb) {
if (arguments.length === 2) {
cb = validation_function;
validation_function = null;
cb = validationFunction;
validationFunction = null;
}
var results = [];
@ -67,13 +67,13 @@ var support = {
file = dir + '/' + file;
fs.stat(file, function(err, stat) {
if (stat && stat.isDirectory()) {
support.walk_dir(file, validation_function, function(err, res) {
support.walkDir(file, validationFunction, function(err, res) {
results = results.concat(res);
if (!--pending) { cb(null, results); }
});
} else {
if (typeof validation_function === 'function') {
if (validation_function(file)) {
if (typeof validationFunction === 'function') {
if (validationFunction(file)) {
results.push(file);
}
} else {
@ -87,7 +87,7 @@ var support = {
});
},
test_set_get_del: function(cache, cb) {
testSetGetDel: function(cache, cb) {
var key = 'TEST' + support.random.string();
var val = support.random.string();
var ttl;

Loading…
Cancel
Save