memoize-cache
Advanced tools
Comparing version 2.0.1 to 3.0.0
18
cache.js
@@ -10,8 +10,13 @@ var Promise = require('bluebird'); | ||
function Cache(cacheManager, key, getMaxAge) { | ||
function Cache(cacheManager, opts) { | ||
opts = opts || {}; | ||
this.cacheManager = cacheManager; | ||
Promise.promisifyAll(this.cacheManager); | ||
this.getCacheKey = keyGetter(key); | ||
this._getMaxAge = getMaxAge; | ||
this.getCacheKey = keyGetter(opts.key); | ||
this._getMaxAge = opts.maxAge; | ||
this._maxValidity = typeof opts.maxValidity === 'undefined' ? | ||
function () {return Infinity;} : | ||
(typeof opts.maxValidity === 'function' ? opts.maxValidity : function () {return opts.maxValidity;}); | ||
this._tasksToComplete = []; | ||
@@ -23,2 +28,3 @@ } | ||
var maxAge = this._getMaxAge ? this._getMaxAge.call(this, args, output) : undefined; | ||
var maxValidity = (this._maxValidity.call(this, args, output) * 1000) + Date.now(); | ||
@@ -31,3 +37,4 @@ if (k === null) return; | ||
var task = this.cacheManager.setAsync(k, output, maxAge ? {ttl: maxAge} : undefined); | ||
var data = { data: output, maxValidity: maxValidity }; | ||
var task = this.cacheManager.setAsync(k, data, maxAge ? {ttl: maxAge} : undefined); | ||
this._tasksToComplete.push(task); | ||
@@ -60,3 +67,4 @@ }; | ||
key: key, | ||
hit: res | ||
hit: res.data, | ||
stale: Boolean(res.maxValidity && res.maxValidity < Date.now()) | ||
}); | ||
@@ -63,0 +71,0 @@ } |
@@ -17,4 +17,7 @@ /* | ||
var key = this.getCacheKey.apply(this, args); | ||
if (key === '__error__') { | ||
return next(new Error('Error test')); | ||
} | ||
return next(undefined, { | ||
return next(null, { | ||
cached: false, | ||
@@ -21,0 +24,0 @@ key: key |
{ | ||
"name": "memoize-cache", | ||
"version": "2.0.1", | ||
"version": "3.0.0", | ||
"description": "A cache support for memoized functions", | ||
@@ -5,0 +5,0 @@ "main": "index.js", |
@@ -32,4 +32,8 @@ var sizeof = require('sizeof'); | ||
function () {return Infinity;} : | ||
(typeof opts.maxAge === 'function' ? opts.maxAge : function () {return opts.maxAge;}); | ||
(typeof opts.maxAge === 'function' ? (opts.maxAge) : function () {return opts.maxAge;}); | ||
this._maxValidity = typeof opts.maxValidity === 'undefined' ? | ||
function () {return Infinity;} : | ||
(typeof opts.maxValidity === 'function' ? (opts.maxValidity) : function () {return opts.maxValidity;}); | ||
this._maxLen = opts.maxLen || Infinity; | ||
@@ -41,3 +45,4 @@ } | ||
k = this.getCacheKey.apply(this, args), | ||
maxAge = this._maxAge.call(this, args, output); | ||
maxAge = this._maxAge.call(this, args, output) * 1000, | ||
maxValidity = (this._maxValidity.call(this, args, output) * 1000) + Date.now(); | ||
@@ -58,3 +63,3 @@ if (k === null) return; // if k is null I don't cache | ||
// add to cache | ||
this._cache[k] = output; | ||
this._cache[k] = { data: output, maxValidity: maxValidity }; | ||
@@ -109,4 +114,4 @@ if (this._maxLen !== Infinity) { | ||
// if k is null I don't cache | ||
return next(undefined, { | ||
cached: cached, | ||
return next(null, { | ||
cached: false, | ||
key: key | ||
@@ -131,6 +136,7 @@ }); | ||
next(undefined, { | ||
next(null, { | ||
cached: cached, | ||
key: key, | ||
hit: hit | ||
hit: hit && hit.data, | ||
stale: hit && Boolean(hit.maxValidity && hit.maxValidity < Date.now()) | ||
}); | ||
@@ -137,0 +143,0 @@ }; |
@@ -16,3 +16,4 @@ memoize-cache | ||
* maxLen: the maximum number of items stored in the cache. Default: Infinity. Cache items will be purged using an LRU algorithm | ||
* maxAge: the maximum age of the item stored in the cache (in ms). Default: Infinity. You can also pass a function that will calculate the ttl of a specific item (0 will mean no cache). The function will take the same arguments as the "push" method (an array of inputs and the output). | ||
* maxAge: the maximum age of the item stored in the cache (in seconds). Default: Infinity. You can also pass a function that will calculate the ttl of a specific item (0 will mean no cache). The function will take the same arguments as the "push" method (an array of inputs and the output). | ||
* maxValidity: the maximum age of the item stored in the cache (in seconds) to be considered "not stale". Default: Infinity. You can also pass a function that will calculate the validity of a specific item. The function will take the same arguments as the "push" method (an array of inputs and the output). | ||
@@ -36,8 +37,8 @@ Example: | ||
===== | ||
The constructor takes an cache-manager object, an optional "key" function, and an optional "getMaxAge" function. | ||
The constructor takes an cache-manager object, and an "options" object. | ||
The options object may contain these attributes: | ||
* key: a function used to extract the cache key (used in the push and query method for storing, retrieving the cached value). The key returned should be a string or it will be converted to JSON and then md5. Default: a function returning a fixed key. The value won't be cached if the function returns null | ||
* maxAge: it is a function that allows you to use a different TTL for a specific item (in seconds). If it returns 0 it will avoid caching the item. The function takes the same arguments as the "push" method (an array of inputs and the output). If it returns undefined, the default ttl will be used. | ||
* maxValidity: the maximum age of an item stored in the cache before being considered "stale" (in seconds). Default: Infinity. You can also pass a function that will calculate the validity of a specific item. The function will take the same arguments as the "push" method (an array of inputs and the output). | ||
The "key" function will be used to extract the cache key (used in the push and query method for storing, retrieving the cached value). The key returned should be a string or it will be converted to JSON and then md5. Default: a function returning a fixed key. The value won't be cached if the function returns null. | ||
"getMaxAge" allows you to use a different TTL for a specific item. It must be a function and it takes the same arguments as the "push" method (an array of inputs and the output). It returns the TTL in seconds (YES, THESE ARE SECONDS INSTEAD OF MILLISECONDS!!!). Infinity means: forever, 0 means: don't cache. | ||
If it returns undefined, the default ttl will be used. | ||
Example: | ||
@@ -75,2 +76,3 @@ ```js | ||
// cached.key is the key used to store the value (might be useful for debugging) | ||
// cache.stale (true/false) depending on the maxValidity function (if defined) | ||
}); | ||
@@ -77,0 +79,0 @@ ``` |
@@ -9,3 +9,3 @@ var assert = require('chai').assert; | ||
var memoryCache = cacheManager.caching({store: 'memory', max: 100, ttl: 10}); | ||
var cache = new Cache(memoryCache, function (n) {return n;}); | ||
var cache = new Cache(memoryCache, {key: function (n) {return n;}}); | ||
assert.equal(cache.getCacheKey('1'), '1'); | ||
@@ -28,5 +28,55 @@ assert.equal(cache.getCacheKey(1), 'c4ca4238a0b923820dcc509a6f75849b'); | ||
describe('maxValidity', function () { | ||
var memoryCache; | ||
beforeEach(function () { | ||
memoryCache = cacheManager.caching({store: 'memory', max: 100, ttl: 10}); | ||
}); | ||
it('must use value', function (done) { | ||
var cache = new Cache(memoryCache, {maxValidity: 0.010}); | ||
cache.push([], 'result'); | ||
cache.query({}, function (err, res) { | ||
assert.equal(res.cached, true); | ||
assert.equal(res.stale, false); | ||
assert.equal(res.key, '_default'); | ||
assert.equal(res.hit, 'result'); | ||
done(); | ||
}); | ||
}); | ||
it('must use value (2)', function (done) { | ||
var cache = new Cache(memoryCache, {maxValidity: 0.010}); | ||
cache.push([], 'result'); | ||
setTimeout(function () { | ||
cache.query({}, function (err, res) { | ||
assert.equal(res.cached, true); | ||
assert.equal(res.stale, true); | ||
assert.equal(res.key, '_default'); | ||
assert.equal(res.hit, 'result'); | ||
done(); | ||
}); | ||
}, 15); | ||
}); | ||
it('must use func', function (done) { | ||
var cache = new Cache(memoryCache, {maxValidity: function () { | ||
return 0.010; | ||
}}); | ||
cache.push([], 'result'); | ||
setTimeout(function () { | ||
cache.query({}, function (err, res) { | ||
assert.equal(res.cached, true); | ||
assert.equal(res.stale, true); | ||
assert.equal(res.key, '_default'); | ||
assert.equal(res.hit, 'result'); | ||
done(); | ||
}); | ||
}, 15); | ||
}); | ||
}); | ||
it('must return null key', function () { | ||
var memoryCache = cacheManager.caching({store: 'memory', max: 100, ttl: 10}); | ||
var cache = new Cache(memoryCache, function (n) {return null;}); | ||
var cache = new Cache(memoryCache, {key: function (n) {return null;}}); | ||
assert.equal(cache.getCacheKey('1'), null); | ||
@@ -37,3 +87,3 @@ }); | ||
var memoryCache = cacheManager.caching({store: 'memory', max: 100, ttl: 10}); | ||
var cache = new Cache(memoryCache, function (n) {return null;}); | ||
var cache = new Cache(memoryCache, {key: function (n) {return null;}}); | ||
cache.push([], 'result'); | ||
@@ -50,10 +100,12 @@ cache.query({}, function (err, res) { | ||
var memoryCache = cacheManager.caching({store: 'memory', max: 100, ttl: 10}); | ||
var cache = new Cache(memoryCache, function (n) { | ||
return n; | ||
}, | ||
function (args, output) { | ||
if (output === 'result') { | ||
return 0; | ||
var cache = new Cache(memoryCache, { | ||
key: function (n) { | ||
return n; | ||
}, | ||
maxAge: function (args, output) { | ||
if (output === 'result') { | ||
return 0; | ||
} | ||
return Infinity; | ||
} | ||
return Infinity; | ||
}); | ||
@@ -74,5 +126,5 @@ cache.push(['1'], 'result'); | ||
var memoryCache = cacheManager.caching({store: 'memory', max: 100, ttl: 10}); | ||
cache = new Cache(memoryCache, function (data) { | ||
cache = new Cache(memoryCache, {key: function (data) { | ||
return data.test; | ||
}); | ||
}}); | ||
cache.push([{test: '1'}], 'result1'); | ||
@@ -112,5 +164,5 @@ cache.push([{test: '2'}], 'result2'); | ||
var memoryCache = cacheManager.caching({store: 'memory', max: 100, ttl: 10}); | ||
var cache = new Cache(memoryCache, function (data) { | ||
var cache = new Cache(memoryCache, {key: function (data) { | ||
return data.test; | ||
}); | ||
}}); | ||
cache.push([{test: [1, 2]}], 'result1'); | ||
@@ -129,5 +181,5 @@ cache.push([{test: [3, 4]}], 'result2'); | ||
var memoryCache = cacheManager.caching({store: 'memory', max: 100, ttl: 10}); | ||
var cache = new Cache(memoryCache, function (data) { | ||
var cache = new Cache(memoryCache, {key: function (data) { | ||
return data.test[0]; | ||
}); | ||
}}); | ||
cache.push([{test: [1, 2]}], 'result1'); | ||
@@ -145,5 +197,5 @@ | ||
var memoryCache = cacheManager.caching({store: 'memory', max: 100, ttl: 10}); | ||
var cache = new Cache(memoryCache, function (data) { | ||
var cache = new Cache(memoryCache, {key: function (data) { | ||
return data.test; | ||
}); | ||
}}); | ||
cache.push([{test: [1, 2]}], 'result1'); | ||
@@ -161,5 +213,5 @@ | ||
var memoryCache = cacheManager.caching({store: 'memory', max: 100, ttl: 10}); | ||
var cache = new Cache(memoryCache, function (config) { | ||
var cache = new Cache(memoryCache, {key: function (config) { | ||
return config.test * 2; | ||
}); | ||
}}); | ||
cache.push([{test: 4}], 'result1'); | ||
@@ -180,5 +232,5 @@ | ||
var memoryCache = cacheManager.caching({store: 'memory', max: 2, ttl: 10}); | ||
cache = new Cache(memoryCache, function (data) { | ||
cache = new Cache(memoryCache, {key: function (data) { | ||
return data.test; | ||
}); | ||
}}); | ||
cache.push([{test: '1'}], 'result1'); | ||
@@ -228,5 +280,5 @@ cache.push([{test: '2'}], 'result2'); | ||
var memoryCache = cacheManager.caching({store: 'memory', max: 20, ttl: 0.030}); | ||
cache = new Cache(memoryCache, function (data) { | ||
cache = new Cache(memoryCache, {key: function (data) { | ||
return data.test; | ||
}); | ||
}}); | ||
cache.push([{test: '1'}], 'result1'); | ||
@@ -278,8 +330,10 @@ }); | ||
var memoryCache = cacheManager.caching({store: 'memory', max: 20, ttl: 0.030}); | ||
cache = new Cache(memoryCache, function (data) { | ||
return data.test; | ||
}, | ||
function (args, output) { | ||
var data = args[0]; | ||
return data.test === '1' ? 0 : 0.050; | ||
cache = new Cache(memoryCache, { | ||
key: function (data) { | ||
return data.test; | ||
}, | ||
maxAge: function (args, output) { | ||
var data = args[0]; | ||
return data.test === '1' ? 0 : 0.050; | ||
} | ||
}); | ||
@@ -286,0 +340,0 @@ |
@@ -23,2 +23,3 @@ var assert = require('chai').assert; | ||
assert.equal(res.cached, true); | ||
assert.equal(res.stale, false); | ||
assert.equal(res.key, '_default'); | ||
@@ -30,2 +31,46 @@ assert.equal(res.hit, 'result'); | ||
describe('maxValidity', function () { | ||
it('must use value', function (done) { | ||
var cache = new Cache({maxValidity: 0.010}); | ||
cache.push([], 'result'); | ||
cache.query({}, function (err, res) { | ||
assert.equal(res.cached, true); | ||
assert.equal(res.stale, false); | ||
assert.equal(res.key, '_default'); | ||
assert.equal(res.hit, 'result'); | ||
done(); | ||
}); | ||
}); | ||
it('must use value (2)', function (done) { | ||
var cache = new Cache({maxValidity: 0.010}); | ||
cache.push([], 'result'); | ||
setTimeout(function () { | ||
cache.query({}, function (err, res) { | ||
assert.equal(res.cached, true); | ||
assert.equal(res.stale, true); | ||
assert.equal(res.key, '_default'); | ||
assert.equal(res.hit, 'result'); | ||
done(); | ||
}); | ||
}, 15); | ||
}); | ||
it('must use func', function (done) { | ||
var cache = new Cache({maxValidity: function () { | ||
return 0.010; | ||
}}); | ||
cache.push([], 'result'); | ||
setTimeout(function () { | ||
cache.query({}, function (err, res) { | ||
assert.equal(res.cached, true); | ||
assert.equal(res.stale, true); | ||
assert.equal(res.key, '_default'); | ||
assert.equal(res.hit, 'result'); | ||
done(); | ||
}); | ||
}, 15); | ||
}); | ||
}); | ||
it('must not cache if key is null', function (done) { | ||
@@ -67,3 +112,3 @@ var cache = new Cache({key: function (n) {return null;}}); | ||
cache.push([], 'result'); | ||
assert.equal(cache.size(true), '28B'); | ||
assert.equal(cache.size(true), '66B'); | ||
}); | ||
@@ -85,2 +130,3 @@ | ||
assert.equal(res1.cached, true); | ||
assert.equal(res1.stale, false); | ||
assert.equal(res1.key, '1'); | ||
@@ -95,2 +141,3 @@ assert.equal(res1.hit, 'result1'); | ||
assert.equal(res2.cached, true); | ||
assert.equal(res2.stale, false); | ||
assert.equal(res2.key, '2'); | ||
@@ -121,2 +168,3 @@ assert.equal(res2.hit, 'result2'); | ||
assert.equal(res1.cached, true); | ||
assert.equal(res1.stale, false); | ||
assert.equal(res1.key, 'f79408e5ca998cd53faf44af31e6eb45'); | ||
@@ -136,2 +184,3 @@ assert.equal(res1.hit, 'result1'); | ||
assert.equal(res1.cached, true); | ||
assert.equal(res1.stale, false); | ||
assert.equal(res1.key, 'c4ca4238a0b923820dcc509a6f75849b'); | ||
@@ -235,3 +284,3 @@ assert.equal(res1.hit, 'result1'); | ||
return data.test; | ||
}, maxAge: 30}); | ||
}, maxAge: 0.030}); | ||
cache.push([{test: '1'}], 'result1'); | ||
@@ -288,3 +337,3 @@ }); | ||
var data = args[0]; | ||
return data.test === '1' ? 0 : 50; | ||
return data.test === '1' ? 0 : 0.050; | ||
}}); | ||
@@ -291,0 +340,0 @@ cache.push([{test: '1'}], 'result1'); |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
45247
1161
119