Browse Source

Merge branch 'release/0.16.0'

feature/specify-what-to-cache 0.16.0
Bryan Donovan 10 years ago
parent
commit
8a014ee185
  1. 19
      .jscs.json
  2. 4
      History.md
  3. 40
      examples/example.js
  4. 18
      examples/redis_example/example.js
  5. 30
      examples/redis_example/redis_store.js
  6. 10
      lib/caching.js
  7. 29
      lib/multi_caching.js
  8. 18
      lib/stores/memory.js
  9. 4
      package.json
  10. 278
      test/caching.unit.js
  11. 310
      test/multi_caching.unit.js
  12. 12
      test/run.js
  13. 6
      test/stores/memory.unit.js
  14. 30
      test/support.js

19
.jscs.json

@ -24,6 +24,7 @@
"requireParenthesesAroundIIFE": true,
"requireSpaceBeforeBlockStatements": true,
"disallowNewlineBeforeBlockStatements": true,
"requireSpacesInConditionalExpression": true,
@ -31,6 +32,18 @@
"beforeOpeningCurlyBrace": true
},
"disallowSpacesInAnonymousFunctionExpression": {
"beforeOpeningRoundBrace": true
},
"disallowSpacesInFunctionDeclaration": {
"beforeOpeningRoundBrace": true
},
"disallowSpacesInFunctionExpression": {
"beforeOpeningRoundBrace": true
},
"requireSpaceBeforeBinaryOperators": [
"+",
"-",
@ -62,6 +75,12 @@
"safeContextKeyword": "self",
"maximumLineLength": {
"value": 120,
"allowUrlComments": true,
"allowRegex": true
},
"validateIndentation": 4,
"validateParameterSeparator": ", ",

4
History.md

@ -1,3 +1,7 @@
- 0.16.0 2015-01-07
Get and pass up feature to update higher caches. (#19) - raadad
Minor style tweaks/jscs update.
- 0.15.0 2014-12-18
Moved cache queue before the store get function (up to 2x performance boost). (#18) - aletorrado
Added domain support to make sure the wrap callback function is always called - aletorrado

40
examples/example.js

@ -8,13 +8,13 @@ var ttl; //Can't use a different ttl per set() call with memory cache
//
// Basic usage
//
memory_cache.set('foo', 'bar', ttl, function (err) {
memory_cache.set('foo', 'bar', ttl, function(err) {
if (err) { throw err; }
memory_cache.get('foo', function (err, result) {
memory_cache.get('foo', function(err, result) {
console.log(result);
// >> 'bar'
memory_cache.del('foo', function (err) {
memory_cache.del('foo', function(err) {
if (err) {
console.log(err);
}
@ -23,7 +23,7 @@ memory_cache.set('foo', 'bar', ttl, function (err) {
});
function get_user(id, cb) {
setTimeout(function () {
setTimeout(function() {
console.log("Fetching user from slow database.");
cb(null, {id: id, name: 'Bob'});
}, 100);
@ -38,14 +38,14 @@ var key = 'user_' + user_id;
// Instead of manually managing the cache like this:
function get_cached_user_manually(id, cb) {
memory_cache.get(id, function (err, result) {
memory_cache.get(id, function(err, result) {
if (err) { return cb(err); }
if (result) {
return cb(null, result);
}
get_user(id, function (err, result) {
get_user(id, function(err, result) {
if (err) { return cb(err); }
memory_cache.set(id, result);
cb(null, result);
@ -55,16 +55,16 @@ function get_cached_user_manually(id, cb) {
// ... you can instead use the `wrap` function:
function get_cached_user(id, cb) {
memory_cache.wrap(id, function (cache_callback) {
memory_cache.wrap(id, function(cache_callback) {
get_user(id, cache_callback);
}, cb);
}
get_cached_user(user_id, function (err, user) {
get_cached_user(user_id, function(err, user) {
// First time fetches the user from the (fake) database:
console.log(user);
get_cached_user(user_id, function (err, user) {
get_cached_user(user_id, function(err, user) {
// Second time fetches from cache.
console.log(user);
});
@ -76,15 +76,15 @@ get_cached_user(user_id, function (err, user) {
// { id: 123, name: 'Bob' }
// Same as above, but written differently:
memory_cache.wrap(key, function (cb) {
memory_cache.wrap(key, function(cb) {
get_user(user_id, cb);
}, function (err, user) {
}, function(err, user) {
console.log(user);
// Second time fetches user from memory_cache
memory_cache.wrap(key, function (cb) {
memory_cache.wrap(key, function(cb) {
get_user(user_id, cb);
}, function (err, user) {
}, function(err, user) {
console.log(user);
});
});
@ -97,31 +97,31 @@ var user_id2 = 456;
var key2 = 'user_' + user_id;
var ttl2; //Can't use a different ttl per set() call with memory cache
multi_cache.wrap(key2, function (cb) {
multi_cache.wrap(key2, function(cb) {
get_user(user_id2, cb);
}, function (err, user) {
}, function(err, user) {
console.log(user);
// Second time fetches user from memory_cache, 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) {
multi_cache.wrap(key2, function(cb) {
get_user(user_id2, cb);
}, function (err, user) {
}, function(err, user) {
console.log(user);
});
// Sets in all caches.
multi_cache.set('foo2', 'bar2', ttl2, function (err) {
multi_cache.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) {
multi_cache.get('foo2', function(err, result) {
console.log(result);
// >> 'bar2'
// Delete from all caches
multi_cache.del('foo2', function (err) {
multi_cache.del('foo2', function(err) {
if (err) {
console.log(err);
}

18
examples/redis_example/example.js

@ -10,14 +10,14 @@ var redis_cache = cache_manager.caching({store: redis_store, db: 0, ttl: 100});
var ttl = 60;
console.log("set/get/del example:");
redis_cache.set('foo', 'bar', ttl, function (err) {
redis_cache.set('foo', 'bar', ttl, function(err) {
if (err) { throw err; }
redis_cache.get('foo', function (err, result) {
redis_cache.get('foo', function(err, result) {
if (err) { throw err; }
console.log("result fetched from cache: " + result);
// >> 'bar'
redis_cache.del('foo', function (err) {
redis_cache.del('foo', function(err) {
if (err) { throw err; }
});
});
@ -30,7 +30,7 @@ function create_key(id) {
}
function get_user(id, cb) {
setTimeout(function () {
setTimeout(function() {
console.log("\n\nReturning user from slow database.");
cb(null, {id: id, name: 'Bob'});
}, 100);
@ -38,24 +38,24 @@ function get_user(id, cb) {
function get_user_from_cache(id, cb) {
var key = create_key(id);
redis_cache.wrap(key, function (cache_cb) {
redis_cache.wrap(key, function(cache_cb) {
get_user(user_id, cache_cb);
}, ttl, cb);
}
get_user_from_cache(user_id, function (err, user) {
get_user_from_cache(user_id, function(err, user) {
console.log(user);
// Second time fetches user from redis_cache
get_user_from_cache(user_id, function (err, user) {
get_user_from_cache(user_id, function(err, user) {
console.log("user from second cache request:");
console.log(user);
redis_cache.keys(function (err, keys) {
redis_cache.keys(function(err, keys) {
console.log("keys: " + util.inspect(keys));
var key = create_key(user_id);
redis_cache.del(key, function (err) {
redis_cache.del(key, function(err) {
if (err) { throw err; }
process.exit();
});

30
examples/redis_example/redis_store.js

@ -20,7 +20,7 @@ function redis_store(args) {
var pool = new RedisPool(redis_options);
function connect(cb) {
pool.acquire(function (err, conn) {
pool.acquire(function(err, conn) {
if (err) {
pool.release(conn);
return cb(err);
@ -34,11 +34,11 @@ function redis_store(args) {
});
}
self.get = function (key, cb) {
connect(function (err, conn) {
self.get = function(key, cb) {
connect(function(err, conn) {
if (err) { return cb(err); }
conn.get(key, function (err, result) {
conn.get(key, function(err, result) {
pool.release(conn);
if (err) { return cb(err); }
cb(null, JSON.parse(result));
@ -46,18 +46,18 @@ function redis_store(args) {
});
};
self.set = function (key, value, ttl, cb) {
self.set = function(key, value, ttl, cb) {
var ttlToUse = ttl || ttlDefault;
connect(function (err, conn) {
connect(function(err, conn) {
if (err) { return cb(err); }
if (ttlToUse) {
conn.setex(key, ttlToUse, JSON.stringify(value), function (err, result) {
conn.setex(key, ttlToUse, JSON.stringify(value), function(err, result) {
pool.release(conn);
cb(err, result);
});
} else {
conn.set(key, JSON.stringify(value), function (err, result) {
conn.set(key, JSON.stringify(value), function(err, result) {
pool.release(conn);
cb(err, result);
});
@ -65,27 +65,27 @@ function redis_store(args) {
});
};
self.del = function (key, cb) {
connect(function (err, conn) {
self.del = function(key, cb) {
connect(function(err, conn) {
if (err) { return cb(err); }
conn.del(key, function (err, result) {
conn.del(key, function(err, result) {
pool.release(conn);
cb(err, result);
});
});
};
self.keys = function (pattern, cb) {
self.keys = function(pattern, cb) {
if (typeof pattern === 'function') {
cb = pattern;
pattern = '*';
}
connect(function (err, conn) {
connect(function(err, conn) {
if (err) { return cb(err); }
conn.keys(pattern, function (err, result) {
conn.keys(pattern, function(err, result) {
pool.release(conn);
cb(err, result);
});
@ -96,7 +96,7 @@ function redis_store(args) {
}
module.exports = {
create: function (args) {
create: function(args) {
return redis_store(args);
}
};

10
lib/caching.js

@ -1,7 +1,7 @@
/*jshint maxcomplexity:15*/
var domain = require('domain');
var caching = function (args) {
var caching = function(args) {
args = args || {};
var self = {};
if (typeof args.store === 'object') {
@ -36,7 +36,7 @@ var caching = function (args) {
* console.log(user);
* });
*/
self.wrap = function (key, work, ttl, cb) {
self.wrap = function(key, work, ttl, cb) {
if (typeof ttl === 'function') {
cb = ttl;
ttl = undefined;
@ -57,7 +57,7 @@ var caching = function (args) {
delete self.queues[key];
}
self.store.get(key, function (err, result) {
self.store.get(key, function(err, result) {
if (err && (!self.ignoreCacheErrors)) {
fillCallbacks(err);
} else if (result) {
@ -68,12 +68,12 @@ var caching = function (args) {
.on('error', function(err) {
fillCallbacks(err);
})
.bind(work)(function (err, data) {
.bind(work)(function(err, data) {
if (err) {
fillCallbacks(err);
return;
}
self.store.set(key, data, ttl, function (err) {
self.store.set(key, data, ttl, function(err) {
if (err && (!self.ignoreCacheErrors)) {
fillCallbacks(err);
} else {

29
lib/multi_caching.js

@ -4,7 +4,7 @@ var domain = require('domain');
/**
* Module that lets you specify a hierarchy of caches.
*/
var multi_caching = function (caches) {
var multi_caching = function(caches) {
var self = {};
if (!Array.isArray(caches)) { throw new Error('multi_caching requires an array of caches'); }
@ -12,8 +12,8 @@ var multi_caching = function (caches) {
function get_from_highest_priority_cache(key, cb) {
var i = 0;
async.forEachSeries(caches, function (cache, async_cb) {
cache.store.get(key, function (err, result) {
async.forEachSeries(caches, function(cache, async_cb) {
cache.store.get(key, function(err, result) {
if (err) { return cb(err); }
if (result) {
// break out of async loop.
@ -27,17 +27,16 @@ var multi_caching = function (caches) {
}
function set_in_multiple_caches(caches, opts, cb) {
async.forEach(caches, function (cache, async_cb) {
async.forEach(caches, function(cache, async_cb) {
cache.store.set(opts.key, opts.value, opts.ttl, async_cb);
}, cb);
}
/**
/**
* Looks for an item in cache tiers.
*
* 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) {
if (err) {
@ -65,7 +64,7 @@ var multi_caching = function (caches) {
* If a key doesn't exist in a higher-priority cache but exists in a lower-priority
* cache, it gets set in all higher-priority caches.
*/
self.wrap = function (key, work, ttl, cb) {
self.wrap = function(key, work, ttl, cb) {
if (typeof ttl === 'function') {
cb = ttl;
ttl = undefined;
@ -86,7 +85,7 @@ var multi_caching = function (caches) {
delete self.queues[key];
}
get_from_highest_priority_cache(key, function (err, result, index) {
get_from_highest_priority_cache(key, function(err, result, index) {
if (err) {
return fillCallbacks(err);
} else if (result) {
@ -96,7 +95,7 @@ var multi_caching = function (caches) {
value: result,
ttl: ttl
};
set_in_multiple_caches(caches_to_update, opts, function (err) {
set_in_multiple_caches(caches_to_update, opts, function(err) {
fillCallbacks(err, result);
});
} else {
@ -105,7 +104,7 @@ var multi_caching = function (caches) {
.on('error', function(err) {
fillCallbacks(err);
})
.bind(work)(function (err, data) {
.bind(work)(function(err, data) {
if (err) {
fillCallbacks(err);
return;
@ -115,7 +114,7 @@ var multi_caching = function (caches) {
value: data,
ttl: ttl
};
set_in_multiple_caches(caches, opts, function (err) {
set_in_multiple_caches(caches, opts, function(err) {
if (err) {
fillCallbacks(err);
} else {
@ -127,7 +126,7 @@ var multi_caching = function (caches) {
});
};
self.set = function (key, value, ttl, cb) {
self.set = function(key, value, ttl, cb) {
var opts = {
key: key,
value: value,
@ -136,12 +135,12 @@ var multi_caching = function (caches) {
set_in_multiple_caches(caches, opts, cb);
};
self.get = function (key, cb) {
self.get = function(key, cb) {
get_from_highest_priority_cache(key, cb);
};
self.del = function (key, cb) {
async.forEach(caches, function (cache, async_cb) {
self.del = function(key, cb) {
async.forEach(caches, function(cache, async_cb) {
cache.store.del(key, async_cb);
}, cb);
};

18
lib/stores/memory.js

@ -1,6 +1,6 @@
var Lru = require("lru-cache");
var memory_store = function (args) {
var memory_store = function(args) {
args = args || {};
var self = {};
self.name = 'memory';
@ -12,17 +12,17 @@ var memory_store = function (args) {
var lru_cache = new Lru(lru_opts);
self.set = function (key, value, ttl, cb) {
self.set = function(key, value, ttl, cb) {
lru_cache.set(key, value);
if (cb) {
process.nextTick(cb);
}
};
self.get = function (key, cb) {
self.get = function(key, cb) {
var value = lru_cache.get(key);
if (cb) {
process.nextTick(function () {
process.nextTick(function() {
cb(null, value);
});
} else {
@ -30,24 +30,24 @@ var memory_store = function (args) {
}
};
self.del = function (key, cb) {
self.del = function(key, cb) {
lru_cache.del(key);
if (cb) {
process.nextTick(cb);
}
};
self.reset = function (cb) {
self.reset = function(cb) {
lru_cache.reset();
if (cb) {
process.nextTick(cb);
}
};
self.keys = function (cb) {
self.keys = function(cb) {
var keys = lru_cache.keys();
if (cb) {
process.nextTick(function () {
process.nextTick(function() {
cb(null, keys);
});
} else {
@ -59,7 +59,7 @@ var memory_store = function (args) {
};
var methods = {
create: function (args) {
create: function(args) {
return memory_store(args);
}
};

4
package.json

@ -1,6 +1,6 @@
{
"name": "cache-manager",
"version": "0.15.0",
"version": "0.16.0",
"description": "Cache module for Node.js",
"main": "index.js",
"scripts": {
@ -26,7 +26,7 @@
"devDependencies": {
"coveralls": "^2.3.0",
"istanbul": "^0.2.11",
"jscs": "^1.7.1",
"jscs": "^1.9.0",
"jshint": "^2.5.4",
"mocha": "^1.20.1",
"optimist": "^0.6.1",

278
test/caching.unit.js

@ -9,49 +9,49 @@ var caching = require('../index').caching;
var memory_store = require('../lib/stores/memory');
var methods = {
get_widget: function (name, cb) {
get_widget: function(name, cb) {
cb(null, {name: name});
}
};
describe("caching", function () {
describe("caching", function() {
var cache;
var key;
var ttl = 1;
var name;
var value;
describe("get() and set()", function () {
['memory'].forEach(function (store) {
context("using " + store + " store", function () {
beforeEach(function () {
describe("get() and set()", function() {
['memory'].forEach(function(store) {
context("using " + store + " store", function() {
beforeEach(function() {
cache = caching({store: store});
key = support.random.string(20);
value = support.random.string();
});
it("lets us set and get data in cache", function (done) {
cache.set(key, value, ttl, function (err) {
it("lets us set and get data in cache", function(done) {
cache.set(key, value, ttl, function(err) {
check_err(err);
cache.get(key, function (err, result) {
cache.get(key, function(err, result) {
assert.equal(result, value);
done();
});
});
});
it("lets us set and get data without a callback", function (done) {
it("lets us set and get data without a callback", function(done) {
cache.set(key, value, ttl);
setTimeout(function () {
setTimeout(function() {
var result = cache.get(key);
assert.equal(result, value);
done();
}, 20);
});
it("lets us set and get data without a ttl or callback", function (done) {
it("lets us set and get data without a ttl or callback", function(done) {
cache.set(key, value);
setTimeout(function () {
setTimeout(function() {
var result = cache.get(key);
assert.equal(result, value);
done();
@ -61,27 +61,27 @@ describe("caching", function () {
});
});
describe("del()", function () {
['memory'].forEach(function (store) {
context("using " + store + " store", function () {
beforeEach(function (done) {
describe("del()", function() {
['memory'].forEach(function(store) {
context("using " + store + " store", function() {
beforeEach(function(done) {
cache = caching({store: store});
key = support.random.string(20);
value = support.random.string();
cache.set(key, value, ttl, function (err) {
cache.set(key, value, ttl, function(err) {
check_err(err);
done();
});
});
it("deletes data from cache", function (done) {
cache.get(key, function (err, result) {
it("deletes data from cache", function(done) {
cache.get(key, function(err, result) {
assert.equal(result, value);
cache.del(key, function (err) {
cache.del(key, function(err) {
check_err(err);
cache.get(key, function (err, result) {
cache.get(key, function(err, result) {
assert.ok(!result);
done();
});
@ -89,14 +89,14 @@ describe("caching", function () {
});
});
it("lets us delete data without a callback", function (done) {
cache.get(key, function (err, result) {
it("lets us delete data without a callback", function(done) {
cache.get(key, function(err, result) {
assert.equal(result, value);
cache.del(key);
setTimeout(function () {
cache.get(key, function (err, result) {
setTimeout(function() {
cache.get(key, function(err, result) {
assert.ok(!result);
done();
});
@ -107,15 +107,15 @@ describe("caching", function () {
});
});
describe("reset()", function () {
describe("reset()", function() {
var key2;
var value2;
beforeEach(function (done) {
beforeEach(function(done) {
cache = caching({store: 'memory'});
key = support.random.string(20);
value = support.random.string();
cache.set(key, value, ttl, function (err) {
cache.set(key, value, ttl, function(err) {
check_err(err);
key2 = support.random.string(20);
@ -125,14 +125,14 @@ describe("caching", function () {
});
});
it("clears the cache", function (done) {
cache.reset(function (err) {
it("clears the cache", function(done) {
cache.reset(function(err) {
check_err(err);
cache.get(key, function (err, result) {
cache.get(key, function(err, result) {
assert.ok(!result);
cache.get(key2, function (err, result) {
cache.get(key2, function(err, result) {
assert.ok(!result);
done();
});
@ -140,13 +140,13 @@ describe("caching", function () {
});
});
it("lets us clear the cache without a callback (memory store only)", function (done) {
it("lets us clear the cache without a callback (memory store only)", function(done) {
cache.reset();
setTimeout(function () {
cache.get(key, function (err, result) {
setTimeout(function() {
cache.get(key, function(err, result) {
assert.ok(!result);
cache.get(key2, function (err, result) {
cache.get(key2, function(err, result) {
assert.ok(!result);
done();
});
@ -154,33 +154,33 @@ describe("caching", function () {
}, 10);
});
context("when store has no del() method", function () {
context("when store has no del() method", function() {
var fake_store;
beforeEach(function () {
beforeEach(function() {
fake_store = {
get: function () {},
set: function () {},
get: function() {},
set: function() {},
};
});
it("it doesn't throw an error", function () {
assert.doesNotThrow(function () {
it("it doesn't throw an error", function() {
assert.doesNotThrow(function() {
caching({store: fake_store});
});
});
});
});
describe("setex()", function () {
describe("setex()", function() {
var fake_store;
beforeEach(function () {
beforeEach(function() {
fake_store = {
get: function () {},
set: function () {},
del: function () {},
setex: function () {}
get: function() {},
set: function() {},
del: function() {},
setex: function() {}
};
sinon.stub(fake_store, 'setex');
@ -188,17 +188,17 @@ describe("caching", function () {
cache = caching({store: fake_store});
});
it("passes the params to the underlying store's setex() method", function () {
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'));
});
});
describe("keys()", function () {
describe("keys()", function() {
var key_count;
var saved_keys = [];
beforeEach(function (done) {
beforeEach(function(done) {
key_count = 10;
var processed = 0;
@ -208,7 +208,7 @@ describe("caching", function () {
return processed === key_count;
}
async.until(is_done, function (cb) {
async.until(is_done, function(cb) {
processed += 1;
key = support.random.string(20);
saved_keys.push(key);
@ -217,25 +217,25 @@ describe("caching", function () {
}, done);
});
it("calls back with all keys in cache", function (done) {
cache.keys(function (err, keys) {
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);
done();
});
});
it("lets us get the keys without a callback (memory store only)", function () {
it("lets us get the keys without a callback (memory store only)", function() {
var keys = cache.keys();
assert.deepEqual(keys.sort, saved_keys.sort);
});
});
describe("wrap()", function () {
describe("using memory (lru-cache) store", function () {
describe("wrap()", function() {
describe("using memory (lru-cache) store", function() {
var memory_store_stub;
beforeEach(function () {
beforeEach(function() {
ttl = 0.1;
memory_store_stub = memory_store.create({ttl: ttl});
@ -246,23 +246,23 @@ describe("caching", function () {
name = support.random.string();
});
afterEach(function () {
afterEach(function() {
memory_store.create.restore();
});
context("calls back with the result of the wrapped function", function () {
beforeEach(function () {
context("calls back with the result of the wrapped function", function() {
beforeEach(function() {
sinon.spy(memory_store_stub, 'set');
});
afterEach(function () {
afterEach(function() {
memory_store_stub.set.restore();
});
it("when a ttl is passed in", function (done) {
cache.wrap(key, function (cb) {
it("when a ttl is passed in", function(done) {
cache.wrap(key, function(cb) {
methods.get_widget(name, cb);
}, ttl, function (err, widget) {
}, ttl, function(err, widget) {
check_err(err);
assert.deepEqual(widget, {name: name});
sinon.assert.calledWith(memory_store_stub.set, key, {name: name}, ttl);
@ -270,10 +270,10 @@ describe("caching", function () {
});
});
it("when a ttl is not passed in", function (done) {
cache.wrap(key, function (cb) {
it("when a ttl is not passed in", function(done) {
cache.wrap(key, function(cb) {
methods.get_widget(name, cb);
}, function (err, widget) {
}, function(err, widget) {
check_err(err);
assert.deepEqual(widget, {name: name});
sinon.assert.calledWith(memory_store_stub.set, key, {name: name}, undefined);
@ -282,19 +282,19 @@ describe("caching", function () {
});
});
context("when result is already cached", function () {
context("when result is already cached", function() {
function get_cached_widget(name, cb) {
cache.wrap(key, function (cache_cb) {
cache.wrap(key, function(cache_cb) {
methods.get_widget(name, cache_cb);
}, ttl, cb);
}
beforeEach(function (done) {
get_cached_widget(name, function (err, widget) {
beforeEach(function(done) {
get_cached_widget(name, function(err, widget) {
check_err(err);
assert.ok(widget);
memory_store_stub.get(key, function (err, result) {
memory_store_stub.get(key, function(err, result) {
check_err(err);
assert.ok(result);
@ -305,19 +305,19 @@ describe("caching", function () {
});
});
afterEach(function () {
afterEach(function() {
memory_store_stub.get.restore();
});
it("retrieves data from cache", function (done) {
it("retrieves data from cache", function(done) {
var func_called = false;
cache.wrap(key, function (cb) {
methods.get_widget(name, function (err, result) {
cache.wrap(key, function(cb) {
methods.get_widget(name, function(err, result) {
func_called = true;
cb(err, result);
});
}, ttl, function (err, widget) {
}, ttl, function(err, widget) {
check_err(err);
assert.deepEqual(widget, {name: name});
assert.ok(memory_store_stub.get.calledWith(key));
@ -327,26 +327,26 @@ describe("caching", function () {
});
});
it("expires cached result after ttl seconds", function (done) {
cache.wrap(key, function (cb) {
it("expires cached result after ttl seconds", function(done) {
cache.wrap(key, function(cb) {
methods.get_widget(name, cb);
}, ttl, function (err, widget) {
}, ttl, function(err, widget) {
check_err(err);
assert.deepEqual(widget, {name: name});
memory_store_stub.get(key, function (err, result) {
memory_store_stub.get(key, function(err, result) {
check_err(err);
assert.ok(result);
var func_called = false;
setTimeout(function () {
cache.wrap(key, function (cb) {
methods.get_widget(name, function (err, result) {
setTimeout(function() {
cache.wrap(key, function(cb) {
methods.get_widget(name, function(err, result) {
func_called = true;
cb(err, result);
});
}, function (err, widget) {
}, function(err, widget) {
check_err(err);
assert.ok(func_called);
assert.deepEqual(widget, {name: name});
@ -357,35 +357,35 @@ describe("caching", function () {
});
});
context("when an error is thrown in the work function", function () {
context("when an error is thrown in the work function", function() {
var fake_error;
beforeEach(function() {
fake_error = new Error(support.random.string());
});
it("bubbles up that error", function (done) {
cache.wrap(key, function () {
it("bubbles up that error", function(done) {
cache.wrap(key, function() {
throw fake_error;
}, ttl, function (err) {
}, ttl, function(err) {
assert.equal(err, fake_error);
done();
});
});
});
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) {
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());
sinon.stub(memory_store_stub, 'get', function (key, cb) {
sinon.stub(memory_store_stub, 'get', function(key, cb) {
cb(fake_error);
});
cache.wrap(key, function (cb) {
cache.wrap(key, function(cb) {
methods.get_widget(name, cb);
}, ttl, function (err) {
}, ttl, function(err) {
assert.equal(err, fake_error);
memory_store_stub.get.restore();
done();
@ -393,19 +393,19 @@ describe("caching", function () {
});
});
context("and ignoreCacheErrors is set to true", function () {
it("does not bubble up that error", function (done) {
context("and ignoreCacheErrors is set to true", 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());
sinon.stub(memory_store_stub, 'get', function (key, cb) {
sinon.stub(memory_store_stub, 'get', function(key, cb) {
cb(fake_error);
});
cache.wrap(key, function (cb) {
cache.wrap(key, function(cb) {
methods.get_widget(name, cb);
}, ttl, function (err) {
}, ttl, function(err) {
assert.equal(err, null);
memory_store_stub.get.restore();
done();
@ -414,18 +414,18 @@ 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) {
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());
sinon.stub(memory_store_stub, 'set', function (key, val, ttl, cb) {
sinon.stub(memory_store_stub, 'set', function(key, val, ttl, cb) {
cb(fake_error);
});
cache.wrap(key, function (cb) {
cache.wrap(key, function(cb) {
methods.get_widget(name, cb);
}, ttl, function (err) {
}, ttl, function(err) {
assert.equal(err, fake_error);
memory_store_stub.set.restore();
done();
@ -433,18 +433,18 @@ describe("caching", function () {
});
});
context("and ignoreCacheErrors is set to true", function () {
it("does not bubbles up that error", function (done) {
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());
sinon.stub(memory_store_stub, 'set', function (key, val, ttl, cb) {
sinon.stub(memory_store_stub, 'set', function(key, val, ttl, cb) {
cb(fake_error);
});
cache.wrap(key, function (cb) {
cache.wrap(key, function(cb) {
methods.get_widget(name, cb);
}, ttl, function (err) {
}, ttl, function(err) {
assert.equal(err, null);
memory_store_stub.set.restore();
done();
@ -453,16 +453,16 @@ describe("caching", function () {
});
});
context("when wrapped function calls back with an error", function () {
it("calls back with that error", function (done) {
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) {
sinon.stub(methods, 'get_widget', function(name, cb) {
cb(fake_error, {name: name});
});
cache.wrap(key, function (cb) {
cache.wrap(key, function(cb) {
methods.get_widget(name, cb);
}, ttl, function (err, widget) {
}, ttl, function(err, widget) {
methods.get_widget.restore();
assert.equal(err, fake_error);
assert.ok(!widget);
@ -472,38 +472,38 @@ describe("caching", function () {
});
});
describe("when called multiple times in parallel with same key", function () {
describe("when called multiple times in parallel with same key", function() {
var construct;
beforeEach(function () {
beforeEach(function() {
cache = caching({
store: 'memory',
max: 50,
ttl: 5 * 60
});
construct = sinon.spy(function (val, cb) {
construct = sinon.spy(function(val, cb) {
var timeout = support.random.number(100);
setTimeout(function () {
setTimeout(function() {
cb(null, 'value');
}, timeout);
});
});
it("calls the wrapped function once", function (done) {
it("calls the wrapped function once", function(done) {
var values = [];
for (var i = 0; i < 2; i++) {
values.push(i);
}
async.each(values, function (val, async_cb) {
cache.wrap('key', function (cb) {
async.each(values, function(val, async_cb) {
cache.wrap('key', function(cb) {
construct(val, cb);
}, ttl, function (err, result) {
}, ttl, function(err, result) {
assert.equal(result, 'value');
async_cb(err);
});
}, function (err) {
}, function(err) {
check_err(err);
assert.equal(construct.callCount, 1);
done();
@ -512,44 +512,44 @@ describe("caching", function () {
});
});
describe("instantiating with no store passed in", function () {
it("defaults to 'memory' store", function () {
describe("instantiating with no store passed in", function() {
it("defaults to 'memory' store", function() {
var cache = caching();
assert.equal(cache.store.name, 'memory');
});
});
describe("instantiating with custom store", function () {
it("allows us to pass in our own store object", function (done) {
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});
cache = caching({store: store});
cache.set(key, value, ttl, function (err) {
cache.set(key, value, ttl, function(err) {
check_err(err);
cache.get(key, function (err, result) {
cache.get(key, function(err, result) {
assert.equal(result, value);
done();
});
});
});
it("allows us to pass in a path to our own store", function (done) {
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});
cache.set(key, value, ttl, function (err) {
cache.set(key, value, ttl, function(err) {
check_err(err);
cache.get(key, function (err, result) {
cache.get(key, function(err, result) {
assert.equal(result, value);
done();
});
});
});
it("allows us to pass in a module (uninstantiated)", function (done) {
it("allows us to pass in a module (uninstantiated)", function(done) {
var store = memory_store;
cache = caching({store: store});
cache.set(key, value, ttl, function (err) {
cache.set(key, value, ttl, function(err) {
check_err(err);
cache.get(key, function (err, result) {
cache.get(key, function(err, result) {
assert.equal(result, value);
done();
});

310
test/multi_caching.unit.js

@ -8,12 +8,12 @@ var multi_caching = require('../index').multi_caching;
var memory_store = require('../lib/stores/memory');
var methods = {
get_widget: function (name, cb) {
get_widget: function(name, cb) {
cb(null, {name: name});
}
};
describe("multi_caching", function () {
describe("multi_caching", function() {
var memory_cache;
var memory_cache2;
var memory_cache3;
@ -23,7 +23,7 @@ describe("multi_caching", function () {
var name;
var ttl = 5;
beforeEach(function () {
beforeEach(function() {
memory_ttl = 0.1;
memory_cache = caching({store: 'memory', ttl: memory_ttl});
@ -34,27 +34,27 @@ describe("multi_caching", function () {
name = support.random.string();
});
describe("get(), set(), del()", function () {
describe("get(), set(), del()", function() {
var value;
beforeEach(function () {
beforeEach(function() {
multi_cache = multi_caching([memory_cache, memory_cache2, memory_cache3]);
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) {
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) {
memory_cache.get(key, function(err, result) {
assert.equal(result, value);
memory_cache2.get(key, function (err, result) {
memory_cache2.get(key, function(err, result) {
check_err(err);
assert.equal(result, value);
memory_cache3.get(key, function (err, result) {
memory_cache3.get(key, function(err, result) {
check_err(err);
assert.equal(result, value);
done();
@ -64,19 +64,19 @@ describe("multi_caching", function () {
});
});
it("lets us set data without a callback", function (done) {
it("lets us set data without a callback", function(done) {
multi_cache.set(key, value, ttl);
setTimeout(function () {
multi_cache.get(key, function (err, result) {
setTimeout(function() {
multi_cache.get(key, function(err, result) {
assert.equal(result, value);
memory_cache.get(key, function (err, result) {
memory_cache.get(key, function(err, result) {
assert.equal(result, value);
memory_cache2.get(key, function (err, result) {
memory_cache2.get(key, function(err, result) {
check_err(err);
assert.equal(result, value);
memory_cache3.get(key, function (err, result) {
memory_cache3.get(key, function(err, result) {
check_err(err);
assert.equal(result, value);
done();
@ -87,19 +87,19 @@ describe("multi_caching", function () {
}, 20);
});
it("lets us set data without a ttl or callback", function (done) {
it("lets us set data without a ttl or callback", function(done) {
multi_cache.set(key, value);
setTimeout(function () {
multi_cache.get(key, function (err, result) {
setTimeout(function() {
multi_cache.get(key, function(err, result) {
assert.equal(result, value);
memory_cache.get(key, function (err, result) {
memory_cache.get(key, function(err, result) {
assert.equal(result, value);
memory_cache2.get(key, function (err, result) {
memory_cache2.get(key, function(err, result) {
check_err(err);
assert.equal(result, value);
memory_cache3.get(key, function (err, result) {
memory_cache3.get(key, function(err, result) {
check_err(err);
assert.equal(result, value);
done();
@ -111,12 +111,12 @@ 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) {
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);
multi_cache.get(key, function (err, result) {
multi_cache.get(key, function(err, result) {
check_err(err);
assert.equal(result, value);
done();
@ -125,22 +125,22 @@ 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) {
describe("del()", function() {
it("lets us delete data in all caches", function(done) {
multi_cache.set(key, value, ttl, function(err) {
check_err(err);
multi_cache.del(key, function (err) {
multi_cache.del(key, function(err) {
check_err(err);
memory_cache.get(key, function (err, result) {
memory_cache.get(key, function(err, result) {
assert.ok(!result);
memory_cache2.get(key, function (err, result) {
memory_cache2.get(key, function(err, result) {
check_err(err);
assert.ok(!result);
memory_cache3.get(key, function (err, result) {
memory_cache3.get(key, function(err, result) {
check_err(err);
assert.ok(!result);
done();
@ -151,21 +151,21 @@ describe("multi_caching", function () {
});
});
it("lets us delete data without a callback", function (done) {
multi_cache.set(key, value, ttl, function (err) {
it("lets us delete data without a callback", function(done) {
multi_cache.set(key, value, ttl, function(err) {
check_err(err);
multi_cache.del(key);
setTimeout(function () {
memory_cache.get(key, function (err, result) {
setTimeout(function() {
memory_cache.get(key, function(err, result) {
assert.ok(!result);
memory_cache2.get(key, function (err, result) {
memory_cache2.get(key, function(err, result) {
check_err(err);
assert.ok(!result);
memory_cache3.get(key, function (err, result) {
memory_cache3.get(key, function(err, result) {
check_err(err);
assert.ok(!result);
done();
@ -178,22 +178,22 @@ describe("multi_caching", function () {
});
});
describe("get_and_pass_up()", function () {
describe("get_and_pass_up()", function() {
var value;
var key;
describe("using a single cache store", function () {
beforeEach(function () {
describe("using a single cache store", function() {
beforeEach(function() {
multi_cache = multi_caching([memory_cache3]);
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) {
it("gets data from first cache that has it", function(done) {
memory_cache3.set(key, value, ttl, function(err) {
check_err(err);
multi_cache.get_and_pass_up(key, function (err, result) {
multi_cache.get_and_pass_up(key, function(err, result) {
check_err(err);
assert.equal(result, value);
done();
@ -211,7 +211,7 @@ describe("multi_caching", function () {
sinon.spy(memory_cache2, 'set');
sinon.spy(memory_cache3, 'set');
multi_cache.get_and_pass_up(key, function (err, result) {
multi_cache.get_and_pass_up(key, function(err, result) {
check_err(err);
response = result;
done();
@ -229,7 +229,7 @@ describe("multi_caching", function () {
});
it("does not set anything in caches", function(done) {
process.nextTick(function () {
process.nextTick(function() {
assert.ok(memory_cache.set.notCalled);
assert.ok(memory_cache2.set.notCalled);
assert.ok(memory_cache3.set.notCalled);
@ -238,23 +238,23 @@ describe("multi_caching", function () {
});
});
describe("using multi cache store", function () {
beforeEach(function () {
multi_cache = multi_caching([memory_cache,memory_cache2,memory_cache3]);
describe("using multi cache store", function() {
beforeEach(function() {
multi_cache = multi_caching([memory_cache, memory_cache2, memory_cache3]);
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) {
it("checks to see if higher levels have item", function(done) {
memory_cache3.set(key, value, ttl, function(err) {
check_err(err);
multi_cache.get_and_pass_up(key, function (err, result) {
multi_cache.get_and_pass_up(key, function(err, result) {
check_err(err);
assert.equal(result, value);
process.nextTick(function() {
memory_cache.get(key, function (err, result) {
memory_cache.get(key, function(err, result) {
assert.equal(result, value);
check_err(err);
done();
@ -266,25 +266,25 @@ describe("multi_caching", function () {
});
});
describe("wrap()", function () {
describe("using a single cache store", function () {
beforeEach(function () {
describe("wrap()", function() {
describe("using a single cache store", function() {
beforeEach(function() {
multi_cache = multi_caching([memory_cache3]);
});
context("calls back with the result of a function", function () {
beforeEach(function () {
context("calls back with the result of a function", function() {
beforeEach(function() {
sinon.spy(memory_cache3.store, 'set');
});
afterEach(function () {
afterEach(function() {
memory_cache3.store.set.restore();
});
it('when a ttl is passed in', function (done) {
multi_cache.wrap(key, function (cb) {
it('when a ttl is passed in', function(done) {
multi_cache.wrap(key, function(cb) {
methods.get_widget(name, cb);
}, ttl, function (err, widget) {
}, ttl, function(err, widget) {
check_err(err);
assert.deepEqual(widget, {name: name});
sinon.assert.calledWith(memory_cache3.store.set, key, {name: name}, ttl);
@ -292,10 +292,10 @@ describe("multi_caching", function () {
});
});
it('when a ttl is not passed in', function (done) {
multi_cache.wrap(key, function (cb) {
it('when a ttl is not passed in', function(done) {
multi_cache.wrap(key, function(cb) {
methods.get_widget(name, cb);
}, function (err, widget) {
}, function(err, widget) {
check_err(err);
assert.deepEqual(widget, {name: name});
sinon.assert.calledWith(memory_cache3.store.set, key, {name: name});
@ -304,16 +304,16 @@ describe("multi_caching", function () {
});
});
context("when wrapped function calls back with an error", function () {
it("calls back with that error", function (done) {
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) {
sinon.stub(methods, 'get_widget', function(name, cb) {
cb(fake_error, {name: name});
});
multi_cache.wrap(key, function (cb) {
multi_cache.wrap(key, function(cb) {
methods.get_widget(name, cb);
}, function (err, widget) {
}, function(err, widget) {
methods.get_widget.restore();
assert.equal(err, fake_error);
assert.ok(!widget);
@ -323,33 +323,33 @@ describe("multi_caching", function () {
});
});
describe("using two cache stores", function () {
beforeEach(function () {
describe("using two cache stores", function() {
beforeEach(function() {
multi_cache = multi_caching([memory_cache, memory_cache3]);
});
it("calls back with the result of a function", function (done) {
multi_cache.wrap(key, function (cb) {
it("calls back with the result of a function", function(done) {
multi_cache.wrap(key, function(cb) {
methods.get_widget(name, cb);
}, function (err, widget) {
}, function(err, widget) {
check_err(err);
assert.deepEqual(widget, {name: name});
done();
});
});
it("sets value in all caches", function (done) {
multi_cache.wrap(key, function (cb) {
it("sets value in all caches", function(done) {
multi_cache.wrap(key, function(cb) {
methods.get_widget(name, cb);
}, function (err, widget) {
}, function(err, widget) {
check_err(err);
assert.deepEqual(widget, {name: name});
memory_cache.get(key, function (err, result) {
memory_cache.get(key, function(err, result) {
check_err(err);
assert.deepEqual(result, {name: name});
memory_cache3.get(key, function (err, result) {
memory_cache3.get(key, function(err, result) {
check_err(err);
assert.deepEqual(result, {name: name});
done();
@ -358,18 +358,18 @@ 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) {
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);
multi_cache.wrap(key, function (cb) {
multi_cache.wrap(key, function(cb) {
methods.get_widget(name, cb);
}, function (err, widget) {
}, function(err, widget) {
check_err(err);
assert.deepEqual(widget, {name: name});
memory_cache3.get(key, function (err, result) {
memory_cache3.get(key, function(err, result) {
check_err(err);
assert.equal(result, null);
done();
@ -379,18 +379,18 @@ 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) {
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);
multi_cache.wrap(key, function (cb) {
multi_cache.wrap(key, function(cb) {
methods.get_widget(name, cb);
}, function (err, widget) {
}, function(err, widget) {
check_err(err);
assert.deepEqual(widget, {name: name});
memory_cache.get(key, function (err, result) {
memory_cache.get(key, function(err, result) {
check_err(err);
assert.deepEqual(result, {name: name});
done();
@ -401,37 +401,37 @@ describe("multi_caching", function () {
});
});
describe("using three cache stores", function () {
beforeEach(function () {
describe("using three cache stores", function() {
beforeEach(function() {
multi_cache = multi_caching([memory_cache, memory_cache3, memory_cache2]);
});
it("calls back with the result of a function", function (done) {
multi_cache.wrap(key, function (cb) {
it("calls back with the result of a function", function(done) {
multi_cache.wrap(key, function(cb) {
methods.get_widget(name, cb);
}, function (err, widget) {
}, function(err, widget) {
check_err(err);
assert.deepEqual(widget, {name: name});
done();
});
});
it("sets value in all caches", function (done) {
multi_cache.wrap(key, function (cb) {
it("sets value in all caches", function(done) {
multi_cache.wrap(key, function(cb) {
methods.get_widget(name, cb);
}, function (err, widget) {
}, function(err, widget) {
check_err(err);
assert.deepEqual(widget, {name: name});
memory_cache.get(key, function (err, result) {
memory_cache.get(key, function(err, result) {
check_err(err);
assert.deepEqual(result, {name: name});
memory_cache2.get(key, function (err, result) {
memory_cache2.get(key, function(err, result) {
check_err(err);
assert.deepEqual(result, {name: name});
memory_cache3.get(key, function (err, result) {
memory_cache3.get(key, function(err, result) {
check_err(err);
assert.deepEqual(result, {name: name});
done();
@ -441,22 +441,22 @@ 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) {
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);
multi_cache.wrap(key, function (cb) {
multi_cache.wrap(key, function(cb) {
methods.get_widget(name, cb);
}, function (err, widget) {
}, function(err, widget) {
check_err(err);
assert.deepEqual(widget, {name: name});
memory_cache2.get(key, function (err, result) {
memory_cache2.get(key, function(err, result) {
check_err(err);
assert.equal(result, null);
memory_cache3.get(key, function (err, result) {
memory_cache3.get(key, function(err, result) {
check_err(err);
assert.equal(result, null);
done();
@ -467,22 +467,22 @@ 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) {
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);
multi_cache.wrap(key, function (cb) {
multi_cache.wrap(key, function(cb) {
methods.get_widget(name, cb);
}, function (err, widget) {
}, function(err, widget) {
check_err(err);
assert.deepEqual(widget, {name: name});
memory_cache.get(key, function (err, result) {
memory_cache.get(key, function(err, result) {
check_err(err);
assert.deepEqual(result, {name: name});
memory_cache2.get(key, function (err, result) {
memory_cache2.get(key, function(err, result) {
check_err(err);
assert.equal(result, null);
done();
@ -493,22 +493,22 @@ 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) {
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);
multi_cache.wrap(key, function (cb) {
multi_cache.wrap(key, function(cb) {
methods.get_widget(name, cb);
}, function (err, widget) {
}, function(err, widget) {
check_err(err);
assert.deepEqual(widget, {name: name});
memory_cache3.get(key, function (err, result) {
memory_cache3.get(key, function(err, result) {
check_err(err);
assert.deepEqual(result, {name: name});
memory_cache.get(key, function (err, result) {
memory_cache.get(key, function(err, result) {
check_err(err);
assert.deepEqual(result, {name: name});
@ -521,11 +521,11 @@ describe("multi_caching", function () {
});
});
context("error handling", function () {
context("error handling", function() {
var memory_store_stub;
var ttl;
beforeEach(function () {
beforeEach(function() {
ttl = 0.1;
memory_store_stub = memory_store.create({ttl: ttl});
sinon.stub(memory_store, 'create').returns(memory_store_stub);
@ -533,38 +533,38 @@ describe("multi_caching", function () {
multi_cache = multi_caching([memory_cache]);
});
afterEach(function () {
afterEach(function() {
memory_store.create.restore();
});
context("when an error is thrown in the work function", function () {
context("when an error is thrown in the work function", function() {
var fake_error;
beforeEach(function() {
fake_error = new Error(support.random.string());
});
it("bubbles up that error", function (done) {
multi_cache.wrap(key, function () {
it("bubbles up that error", function(done) {
multi_cache.wrap(key, function() {
throw fake_error;
}, ttl, function (err) {
}, ttl, function(err) {
assert.equal(err, fake_error);
done();
});
});
});
context("when store.get() calls back with an error", function () {
it("bubbles up that error", function (done) {
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());
sinon.stub(memory_store_stub, 'get', function (key, cb) {
sinon.stub(memory_store_stub, 'get', function(key, cb) {
cb(fake_error);
});
multi_cache.wrap(key, function (cb) {
multi_cache.wrap(key, function(cb) {
methods.get_widget(name, cb);
}, function (err) {
}, function(err) {
assert.equal(err, fake_error);
memory_store_stub.get.restore();
done();
@ -572,17 +572,17 @@ describe("multi_caching", function () {
});
});
context("when store.set() calls back with an error", function () {
it("bubbles up that error", function (done) {
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());
sinon.stub(memory_store_stub, 'set', function (key, val, ttl, cb) {
sinon.stub(memory_store_stub, 'set', function(key, val, ttl, cb) {
cb(fake_error);
});
multi_cache.wrap(key, function (cb) {
multi_cache.wrap(key, function(cb) {
methods.get_widget(name, cb);
}, function (err) {
}, function(err) {
assert.equal(err, fake_error);
memory_store_stub.set.restore();
done();
@ -591,34 +591,34 @@ describe("multi_caching", function () {
});
});
describe("when called multiple times in parallel with same key", function () {
describe("when called multiple times in parallel with same key", function() {
var construct;
beforeEach(function () {
beforeEach(function() {
multi_cache = multi_caching([memory_cache, memory_cache3]);
construct = sinon.spy(function (val, cb) {
construct = sinon.spy(function(val, cb) {
var timeout = support.random.number(100);
setTimeout(function () {
setTimeout(function() {
cb(null, 'value');
}, timeout);
});
});
it("calls the wrapped function once", function (done) {
it("calls the wrapped function once", function(done) {
var values = [];
for (var i = 0; i < 5; i++) {
values.push(i);
}
async.each(values, function (val, async_cb) {
multi_cache.wrap('key', function (cb) {
async.each(values, function(val, async_cb) {
multi_cache.wrap('key', function(cb) {
construct(val, cb);
}, function (err, result) {
}, function(err, result) {
assert.equal(result, 'value');
async_cb(err);
});
}, function (err) {
}, function(err) {
check_err(err);
assert.equal(construct.callCount, 1);
done();
@ -627,9 +627,9 @@ describe("multi_caching", function () {
});
});
context("when instantiated with a non-Array 'caches' arg", function () {
it("throws an error", function () {
assert.throws(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/);
});

12
test/run.js

@ -25,7 +25,7 @@ var valid_test_types = ['unit', 'functional', 'acceptance', 'integration'];
var requested_types = argv.types.split(',');
var types_to_use = [];
valid_test_types.forEach(function (valid_test_type) {
valid_test_types.forEach(function(valid_test_type) {
if (requested_types.indexOf(valid_test_type) !== -1) {
types_to_use.push(valid_test_type);
}
@ -36,7 +36,7 @@ if (argv.help || types_to_use.length === 0) {
process.exit();
}
var is_valid_file = function (file) {
var is_valid_file = function(file) {
if (file.match(/buster/)) {
return false;
}
@ -54,10 +54,10 @@ var is_valid_file = function (file) {
};
function run(cb) {
walk_dir('test', is_valid_file, function (err, files) {
walk_dir('test', is_valid_file, function(err, files) {
if (err) { return cb(err); }
files.forEach(function (file) {
files.forEach(function(file) {
mocha.addFile(file);
});
@ -65,9 +65,9 @@ function run(cb) {
});
}
run(function (err) {
run(function(err) {
if (err) { throw err; }
mocha.run(function (failures) {
mocha.run(function(failures) {
process.exit(failures);
});
});

6
test/stores/memory.unit.js

@ -1,9 +1,9 @@
var support = require('../support');
var memory_store = require('../../lib/stores/memory');
describe("memory store", function () {
describe("instantiating", function () {
it("lets us pass in no args", function (done) {
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);
});

30
test/support.js

@ -4,7 +4,7 @@ var assert = require('assert');
var support = {
random: {
string: function (str_len) {
string: function(str_len) {
str_len = str_len || 8;
var chars = "abcdefghiklmnopqrstuvwxyz";
var random_str = '';
@ -15,13 +15,13 @@ var support = {
return random_str;
},
number: function (max) {
number: function(max) {
max = max || 1000;
return Math.floor((Math.random() * max));
}
},
check_err: function (err) {
check_err: function(err) {
if (err) {
var msg;
@ -38,36 +38,36 @@ var support = {
}
},
assert_between: function (actual, lower, upper) {
assert_between: 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) {
assert_within: function(actual, expected, delta) {
var lower = expected - delta;
var upper = expected + delta;
this.assert_between(actual, lower, upper);
},
walk_dir: function (dir, validation_function, cb) {
walk_dir: function(dir, validation_function, cb) {
if (arguments.length === 2) {
cb = validation_function;
validation_function = null;
}
var results = [];
fs.readdir(dir, function (err, list) {
fs.readdir(dir, function(err, list) {
if (err) { return cb(err); }
var pending = list.length;
if (!pending) { return cb(null, results); }
list.forEach(function (file) {
list.forEach(function(file) {
file = dir + '/' + file;
fs.stat(file, function (err, stat) {
fs.stat(file, function(err, stat) {
if (stat && stat.isDirectory()) {
support.walk_dir(file, validation_function, function (err, res) {
support.walk_dir(file, validation_function, function(err, res) {
results = results.concat(res);
if (!--pending) { cb(null, results); }
});
@ -87,22 +87,22 @@ var support = {
});
},
test_set_get_del: function (cache, cb) {
test_set_get_del: function(cache, cb) {
var key = 'TEST' + support.random.string();
var val = support.random.string();
var ttl;
cache.set(key, val, ttl, function (err) {
cache.set(key, val, ttl, function(err) {
if (err) { return cb(err); }
cache.get(key, function (err, result) {
cache.get(key, function(err, result) {
if (err) { return cb(err); }
assert.equal(result, val);
cache.del(key, function (err) {
cache.del(key, function(err) {
if (err) { return cb(err); }
cache.get(key, function (err, result) {
cache.get(key, function(err, result) {
if (err) { return cb(err); }
assert.ok(!result);
cb();

Loading…
Cancel
Save