|
@ -3,16 +3,33 @@ var domain = require('domain'); |
|
|
var CallbackFiller = require('./callback_filler'); |
|
|
var CallbackFiller = require('./callback_filler'); |
|
|
|
|
|
|
|
|
/** |
|
|
/** |
|
|
|
|
|
* |
|
|
* Module that lets you specify a hierarchy of caches. |
|
|
* Module that lets you specify a hierarchy of caches. |
|
|
|
|
|
* @param {array} caches - Array of caching objects. |
|
|
|
|
|
* @param {object} [options] |
|
|
|
|
|
* @param {function} [options.isCacheableValue] - A callback function which is called |
|
|
|
|
|
* with every value returned from cache or from a wrapped function. This lets you specify |
|
|
|
|
|
* which values should and should not be cached. If the function returns true, it will be |
|
|
|
|
|
* stored in cache. By default it caches everything except undefined. |
|
|
*/ |
|
|
*/ |
|
|
var multiCaching = function(caches) { |
|
|
var multiCaching = function(caches, options) { |
|
|
var self = {}; |
|
|
var self = {}; |
|
|
|
|
|
options = options || {}; |
|
|
|
|
|
|
|
|
if (!Array.isArray(caches)) { |
|
|
if (!Array.isArray(caches)) { |
|
|
throw new Error('multiCaching requires an array of caches'); |
|
|
throw new Error('multiCaching requires an array of caches'); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
var callbackFiller = new CallbackFiller(); |
|
|
var callbackFiller = new CallbackFiller(); |
|
|
|
|
|
|
|
|
|
|
|
if (typeof options.isCacheableValue === 'function') { |
|
|
|
|
|
self._isCacheableValue = options.isCacheableValue; |
|
|
|
|
|
} else { |
|
|
|
|
|
self._isCacheableValue = function(value) { |
|
|
|
|
|
return value !== undefined; |
|
|
|
|
|
}; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
function getFromHighestPriorityCache(key, options, cb) { |
|
|
function getFromHighestPriorityCache(key, options, cb) { |
|
|
if (typeof options === 'function') { |
|
|
if (typeof options === 'function') { |
|
|
cb = options; |
|
|
cb = options; |
|
@ -54,8 +71,10 @@ var multiCaching = function(caches) { |
|
|
|
|
|
|
|
|
/** |
|
|
/** |
|
|
* Looks for an item in cache tiers. |
|
|
* Looks for an item in cache tiers. |
|
|
|
|
|
* When a key is found in a lower cache, all higher levels are updated. |
|
|
* |
|
|
* |
|
|
* When a key is found in a lower cache, all higher levels are updated |
|
|
* @param {string} key |
|
|
|
|
|
* @param {function} cb |
|
|
*/ |
|
|
*/ |
|
|
self.getAndPassUp = function(key, cb) { |
|
|
self.getAndPassUp = function(key, cb) { |
|
|
getFromHighestPriorityCache(key, function(err, result, index) { |
|
|
getFromHighestPriorityCache(key, function(err, result, index) { |
|
@ -91,6 +110,11 @@ var multiCaching = function(caches) { |
|
|
* without getting set in other lower-priority caches. |
|
|
* without getting set in other lower-priority caches. |
|
|
* If a key doesn't exist in a higher-priority cache but exists in a lower-priority |
|
|
* 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. |
|
|
* cache, it gets set in all higher-priority caches. |
|
|
|
|
|
* |
|
|
|
|
|
* @param {string} key - The cache key to use in cache operations |
|
|
|
|
|
* @param {function} work - The function to wrap |
|
|
|
|
|
* @param {object} [options] - options passed to `set` function |
|
|
|
|
|
* @param {function} cb |
|
|
*/ |
|
|
*/ |
|
|
self.wrap = function(key, work, options, cb) { |
|
|
self.wrap = function(key, work, options, cb) { |
|
|
if (typeof options === 'function') { |
|
|
if (typeof options === 'function') { |
|
@ -119,7 +143,7 @@ var multiCaching = function(caches) { |
|
|
getFromHighestPriorityCache(key, function(err, result, index) { |
|
|
getFromHighestPriorityCache(key, function(err, result, index) { |
|
|
if (err) { |
|
|
if (err) { |
|
|
return callbackFiller.fill(key, err); |
|
|
return callbackFiller.fill(key, err); |
|
|
} else if (result) { |
|
|
} else if (self._isCacheableValue(result)) { |
|
|
var cachesToUpdate = caches.slice(0, index); |
|
|
var cachesToUpdate = caches.slice(0, index); |
|
|
var opts = getOptsForSet(result); |
|
|
var opts = getOptsForSet(result); |
|
|
|
|
|
|
|
@ -137,6 +161,10 @@ var multiCaching = function(caches) { |
|
|
return callbackFiller.fill(key, err); |
|
|
return callbackFiller.fill(key, err); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (!self._isCacheableValue(data)) { |
|
|
|
|
|
return cb(); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
var opts = getOptsForSet(data); |
|
|
var opts = getOptsForSet(data); |
|
|
|
|
|
|
|
|
setInMultipleCaches(caches, opts, function(err) { |
|
|
setInMultipleCaches(caches, opts, function(err) { |
|
@ -147,6 +175,13 @@ var multiCaching = function(caches) { |
|
|
}); |
|
|
}); |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
* Set value in all caches |
|
|
|
|
|
* @param {string} key |
|
|
|
|
|
* @param {*} value |
|
|
|
|
|
* @param {object} [options] to pass to underlying set function. |
|
|
|
|
|
* @param {function} cb |
|
|
|
|
|
*/ |
|
|
self.set = function(key, value, options, cb) { |
|
|
self.set = function(key, value, options, cb) { |
|
|
var opts = { |
|
|
var opts = { |
|
|
key: key, |
|
|
key: key, |
|
@ -159,6 +194,12 @@ var multiCaching = function(caches) { |
|
|
setInMultipleCaches(caches, opts, cb); |
|
|
setInMultipleCaches(caches, opts, cb); |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
* Get value from highest level cache that has stored it. |
|
|
|
|
|
* @param {string} key |
|
|
|
|
|
* @param {object} [options] to pass to underlying get function. |
|
|
|
|
|
* @param {function} cb |
|
|
|
|
|
*/ |
|
|
self.get = function(key, options, cb) { |
|
|
self.get = function(key, options, cb) { |
|
|
if (typeof options === 'function') { |
|
|
if (typeof options === 'function') { |
|
|
cb = options; |
|
|
cb = options; |
|
@ -167,6 +208,12 @@ var multiCaching = function(caches) { |
|
|
getFromHighestPriorityCache(key, options, cb); |
|
|
getFromHighestPriorityCache(key, options, cb); |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
* Delete value from all caches. |
|
|
|
|
|
* @param {string} key |
|
|
|
|
|
* @param {object} [options] to pass to underlying del function. |
|
|
|
|
|
* @param {function} cb |
|
|
|
|
|
*/ |
|
|
self.del = function(key, options, cb) { |
|
|
self.del = function(key, options, cb) { |
|
|
if (typeof options === 'function') { |
|
|
if (typeof options === 'function') { |
|
|
cb = options; |
|
|
cb = options; |
|
|