803 lines
23 KiB
JavaScript
803 lines
23 KiB
JavaScript
|
/*
|
|||
|
* node-cache 5.1.2 ( 2020-07-01 )
|
|||
|
* https://github.com/node-cache/node-cache
|
|||
|
*
|
|||
|
* Released under the MIT license
|
|||
|
* https://github.com/node-cache/node-cache/blob/master/LICENSE
|
|||
|
*
|
|||
|
* Maintained by ( )
|
|||
|
*/
|
|||
|
(function() {
|
|||
|
var EventEmitter, NodeCache, clone,
|
|||
|
splice = [].splice,
|
|||
|
boundMethodCheck = function(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new Error('Bound instance method accessed before binding'); } },
|
|||
|
indexOf = [].indexOf;
|
|||
|
|
|||
|
clone = require("clone");
|
|||
|
|
|||
|
EventEmitter = require('events').EventEmitter;
|
|||
|
|
|||
|
// generate superclass
|
|||
|
module.exports = NodeCache = (function() {
|
|||
|
class NodeCache extends EventEmitter {
|
|||
|
constructor(options = {}) {
|
|||
|
super();
|
|||
|
// ## get
|
|||
|
|
|||
|
// get a cached key and change the stats
|
|||
|
|
|||
|
// **Parameters:**
|
|||
|
|
|||
|
// * `key` ( String | Number ): cache key
|
|||
|
|
|||
|
// **Example:**
|
|||
|
|
|||
|
// myCache.get "myKey", ( err, val )
|
|||
|
|
|||
|
this.get = this.get.bind(this);
|
|||
|
// ## mget
|
|||
|
|
|||
|
// get multiple cached keys at once and change the stats
|
|||
|
|
|||
|
// **Parameters:**
|
|||
|
|
|||
|
// * `keys` ( String|Number[] ): an array of keys
|
|||
|
|
|||
|
// **Example:**
|
|||
|
|
|||
|
// myCache.mget [ "foo", "bar" ]
|
|||
|
|
|||
|
this.mget = this.mget.bind(this);
|
|||
|
// ## set
|
|||
|
|
|||
|
// set a cached key and change the stats
|
|||
|
|
|||
|
// **Parameters:**
|
|||
|
|
|||
|
// * `key` ( String | Number ): cache key
|
|||
|
// * `value` ( Any ): A element to cache. If the option `option.forceString` is `true` the module trys to translate it to a serialized JSON
|
|||
|
// * `[ ttl ]` ( Number | String ): ( optional ) The time to live in seconds.
|
|||
|
|
|||
|
// **Example:**
|
|||
|
|
|||
|
// myCache.set "myKey", "my_String Value"
|
|||
|
|
|||
|
// myCache.set "myKey", "my_String Value", 10
|
|||
|
|
|||
|
this.set = this.set.bind(this);
|
|||
|
|
|||
|
// ## mset
|
|||
|
|
|||
|
// set multiple keys at once
|
|||
|
|
|||
|
// **Parameters:**
|
|||
|
|
|||
|
// * `keyValueSet` ( Object[] ): an array of object which includes key,value and ttl
|
|||
|
|
|||
|
// **Example:**
|
|||
|
|
|||
|
// myCache.mset(
|
|||
|
// [
|
|||
|
// {
|
|||
|
// key: "myKey",
|
|||
|
// val: "myValue",
|
|||
|
// ttl: [ttl in seconds]
|
|||
|
// }
|
|||
|
// ])
|
|||
|
|
|||
|
this.mset = this.mset.bind(this);
|
|||
|
// ## del
|
|||
|
|
|||
|
// remove keys
|
|||
|
|
|||
|
// **Parameters:**
|
|||
|
|
|||
|
// * `keys` ( String | Number | String|Number[] ): cache key to delete or a array of cache keys
|
|||
|
|
|||
|
// **Return**
|
|||
|
|
|||
|
// ( Number ): Number of deleted keys
|
|||
|
|
|||
|
// **Example:**
|
|||
|
|
|||
|
// myCache.del( "myKey" )
|
|||
|
|
|||
|
this.del = this.del.bind(this);
|
|||
|
// ## take
|
|||
|
|
|||
|
// get the cached value and remove the key from the cache.
|
|||
|
// Equivalent to calling `get(key)` + `del(key)`.
|
|||
|
// Useful for implementing `single use` mechanism such as OTP, where once a value is read it will become obsolete.
|
|||
|
|
|||
|
// **Parameters:**
|
|||
|
|
|||
|
// * `key` ( String | Number ): cache key
|
|||
|
|
|||
|
// **Example:**
|
|||
|
|
|||
|
// myCache.take "myKey", ( err, val )
|
|||
|
|
|||
|
this.take = this.take.bind(this);
|
|||
|
// ## ttl
|
|||
|
|
|||
|
// reset or redefine the ttl of a key. `ttl` = 0 means infinite lifetime.
|
|||
|
// If `ttl` is not passed the default ttl is used.
|
|||
|
// If `ttl` < 0 the key will be deleted.
|
|||
|
|
|||
|
// **Parameters:**
|
|||
|
|
|||
|
// * `key` ( String | Number ): cache key to reset the ttl value
|
|||
|
// * `ttl` ( Number ): ( optional -> options.stdTTL || 0 ) The time to live in seconds
|
|||
|
|
|||
|
// **Return**
|
|||
|
|
|||
|
// ( Boolen ): key found and ttl set
|
|||
|
|
|||
|
// **Example:**
|
|||
|
|
|||
|
// myCache.ttl( "myKey" ) // will set ttl to default ttl
|
|||
|
|
|||
|
// myCache.ttl( "myKey", 1000 )
|
|||
|
|
|||
|
this.ttl = this.ttl.bind(this);
|
|||
|
// ## getTtl
|
|||
|
|
|||
|
// receive the ttl of a key.
|
|||
|
|
|||
|
// **Parameters:**
|
|||
|
|
|||
|
// * `key` ( String | Number ): cache key to check the ttl value
|
|||
|
|
|||
|
// **Return**
|
|||
|
|
|||
|
// ( Number|undefined ): The timestamp in ms when the key will expire, 0 if it will never expire or undefined if it not exists
|
|||
|
|
|||
|
// **Example:**
|
|||
|
|
|||
|
// myCache.getTtl( "myKey" )
|
|||
|
|
|||
|
this.getTtl = this.getTtl.bind(this);
|
|||
|
// ## keys
|
|||
|
|
|||
|
// list all keys within this cache
|
|||
|
|
|||
|
// **Return**
|
|||
|
|
|||
|
// ( Array ): An array of all keys
|
|||
|
|
|||
|
// **Example:**
|
|||
|
|
|||
|
// _keys = myCache.keys()
|
|||
|
|
|||
|
// # [ "foo", "bar", "fizz", "buzz", "anotherKeys" ]
|
|||
|
|
|||
|
this.keys = this.keys.bind(this);
|
|||
|
// ## has
|
|||
|
|
|||
|
// Check if a key is cached
|
|||
|
|
|||
|
// **Parameters:**
|
|||
|
|
|||
|
// * `key` ( String | Number ): cache key to check the ttl value
|
|||
|
|
|||
|
// **Return**
|
|||
|
|
|||
|
// ( Boolean ): A boolean that indicates if the key is cached
|
|||
|
|
|||
|
// **Example:**
|
|||
|
|
|||
|
// _exists = myCache.has('myKey')
|
|||
|
|
|||
|
// # true
|
|||
|
|
|||
|
this.has = this.has.bind(this);
|
|||
|
// ## getStats
|
|||
|
|
|||
|
// get the stats
|
|||
|
|
|||
|
// **Parameters:**
|
|||
|
|
|||
|
// -
|
|||
|
|
|||
|
// **Return**
|
|||
|
|
|||
|
// ( Object ): Stats data
|
|||
|
|
|||
|
// **Example:**
|
|||
|
|
|||
|
// myCache.getStats()
|
|||
|
// # {
|
|||
|
// # hits: 0,
|
|||
|
// # misses: 0,
|
|||
|
// # keys: 0,
|
|||
|
// # ksize: 0,
|
|||
|
// # vsize: 0
|
|||
|
// # }
|
|||
|
|
|||
|
this.getStats = this.getStats.bind(this);
|
|||
|
// ## flushAll
|
|||
|
|
|||
|
// flush the whole data and reset the stats
|
|||
|
|
|||
|
// **Example:**
|
|||
|
|
|||
|
// myCache.flushAll()
|
|||
|
|
|||
|
// myCache.getStats()
|
|||
|
// # {
|
|||
|
// # hits: 0,
|
|||
|
// # misses: 0,
|
|||
|
// # keys: 0,
|
|||
|
// # ksize: 0,
|
|||
|
// # vsize: 0
|
|||
|
// # }
|
|||
|
|
|||
|
this.flushAll = this.flushAll.bind(this);
|
|||
|
|
|||
|
// ## flushStats
|
|||
|
|
|||
|
// flush the stats and reset all counters to 0
|
|||
|
|
|||
|
// **Example:**
|
|||
|
|
|||
|
// myCache.flushStats()
|
|||
|
|
|||
|
// myCache.getStats()
|
|||
|
// # {
|
|||
|
// # hits: 0,
|
|||
|
// # misses: 0,
|
|||
|
// # keys: 0,
|
|||
|
// # ksize: 0,
|
|||
|
// # vsize: 0
|
|||
|
// # }
|
|||
|
|
|||
|
this.flushStats = this.flushStats.bind(this);
|
|||
|
// ## close
|
|||
|
|
|||
|
// This will clear the interval timeout which is set on checkperiod option.
|
|||
|
|
|||
|
// **Example:**
|
|||
|
|
|||
|
// myCache.close()
|
|||
|
|
|||
|
this.close = this.close.bind(this);
|
|||
|
// ## _checkData
|
|||
|
|
|||
|
// internal housekeeping method.
|
|||
|
// Check all the cached data and delete the invalid values
|
|||
|
this._checkData = this._checkData.bind(this);
|
|||
|
// ## _check
|
|||
|
|
|||
|
// internal method the check the value. If it's not valid any more delete it
|
|||
|
this._check = this._check.bind(this);
|
|||
|
// ## _isInvalidKey
|
|||
|
|
|||
|
// internal method to check if the type of a key is either `number` or `string`
|
|||
|
this._isInvalidKey = this._isInvalidKey.bind(this);
|
|||
|
// ## _wrap
|
|||
|
|
|||
|
// internal method to wrap a value in an object with some metadata
|
|||
|
this._wrap = this._wrap.bind(this);
|
|||
|
// ## _getValLength
|
|||
|
|
|||
|
// internal method to calculate the value length
|
|||
|
this._getValLength = this._getValLength.bind(this);
|
|||
|
// ## _error
|
|||
|
|
|||
|
// internal method to handle an error message
|
|||
|
this._error = this._error.bind(this);
|
|||
|
// ## _initErrors
|
|||
|
|
|||
|
// internal method to generate error message templates
|
|||
|
this._initErrors = this._initErrors.bind(this);
|
|||
|
this.options = options;
|
|||
|
this._initErrors();
|
|||
|
// container for cached data
|
|||
|
this.data = {};
|
|||
|
// module options
|
|||
|
this.options = Object.assign({
|
|||
|
// convert all elements to string
|
|||
|
forceString: false,
|
|||
|
// used standard size for calculating value size
|
|||
|
objectValueSize: 80,
|
|||
|
promiseValueSize: 80,
|
|||
|
arrayValueSize: 40,
|
|||
|
// standard time to live in seconds. 0 = infinity;
|
|||
|
stdTTL: 0,
|
|||
|
// time in seconds to check all data and delete expired keys
|
|||
|
checkperiod: 600,
|
|||
|
// en/disable cloning of variables. If `true` you'll get a copy of the cached variable. If `false` you'll save and get just the reference
|
|||
|
useClones: true,
|
|||
|
// whether values should be deleted automatically at expiration
|
|||
|
deleteOnExpire: true,
|
|||
|
// enable legacy callbacks
|
|||
|
enableLegacyCallbacks: false,
|
|||
|
// max amount of keys that are being stored
|
|||
|
maxKeys: -1
|
|||
|
}, this.options);
|
|||
|
// generate functions with callbacks (legacy)
|
|||
|
if (this.options.enableLegacyCallbacks) {
|
|||
|
console.warn("WARNING! node-cache legacy callback support will drop in v6.x");
|
|||
|
["get", "mget", "set", "del", "ttl", "getTtl", "keys", "has"].forEach((methodKey) => {
|
|||
|
var oldMethod;
|
|||
|
// reference real function
|
|||
|
oldMethod = this[methodKey];
|
|||
|
this[methodKey] = function(...args) {
|
|||
|
var cb, err, ref, res;
|
|||
|
ref = args, [...args] = ref, [cb] = splice.call(args, -1);
|
|||
|
// return a callback if cb is defined and a function
|
|||
|
if (typeof cb === "function") {
|
|||
|
try {
|
|||
|
res = oldMethod(...args);
|
|||
|
cb(null, res);
|
|||
|
} catch (error1) {
|
|||
|
err = error1;
|
|||
|
cb(err);
|
|||
|
}
|
|||
|
} else {
|
|||
|
return oldMethod(...args, cb);
|
|||
|
}
|
|||
|
};
|
|||
|
});
|
|||
|
}
|
|||
|
// statistics container
|
|||
|
this.stats = {
|
|||
|
hits: 0,
|
|||
|
misses: 0,
|
|||
|
keys: 0,
|
|||
|
ksize: 0,
|
|||
|
vsize: 0
|
|||
|
};
|
|||
|
// pre allocate valid keytypes array
|
|||
|
this.validKeyTypes = ["string", "number"];
|
|||
|
// initalize checking period
|
|||
|
this._checkData();
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
get(key) {
|
|||
|
var _ret, err;
|
|||
|
boundMethodCheck(this, NodeCache);
|
|||
|
// handle invalid key types
|
|||
|
if ((err = this._isInvalidKey(key)) != null) {
|
|||
|
throw err;
|
|||
|
}
|
|||
|
// get data and incremet stats
|
|||
|
if ((this.data[key] != null) && this._check(key, this.data[key])) {
|
|||
|
this.stats.hits++;
|
|||
|
_ret = this._unwrap(this.data[key]);
|
|||
|
// return data
|
|||
|
return _ret;
|
|||
|
} else {
|
|||
|
// if not found return undefined
|
|||
|
this.stats.misses++;
|
|||
|
return void 0;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
mget(keys) {
|
|||
|
var _err, err, i, key, len, oRet;
|
|||
|
boundMethodCheck(this, NodeCache);
|
|||
|
// convert a string to an array of one key
|
|||
|
if (!Array.isArray(keys)) {
|
|||
|
_err = this._error("EKEYSTYPE");
|
|||
|
throw _err;
|
|||
|
}
|
|||
|
// define return
|
|||
|
oRet = {};
|
|||
|
for (i = 0, len = keys.length; i < len; i++) {
|
|||
|
key = keys[i];
|
|||
|
// handle invalid key types
|
|||
|
if ((err = this._isInvalidKey(key)) != null) {
|
|||
|
throw err;
|
|||
|
}
|
|||
|
// get data and increment stats
|
|||
|
if ((this.data[key] != null) && this._check(key, this.data[key])) {
|
|||
|
this.stats.hits++;
|
|||
|
oRet[key] = this._unwrap(this.data[key]);
|
|||
|
} else {
|
|||
|
// if not found return a error
|
|||
|
this.stats.misses++;
|
|||
|
}
|
|||
|
}
|
|||
|
// return all found keys
|
|||
|
return oRet;
|
|||
|
}
|
|||
|
|
|||
|
set(key, value, ttl) {
|
|||
|
var _err, err, existent;
|
|||
|
boundMethodCheck(this, NodeCache);
|
|||
|
// check if cache is overflowing
|
|||
|
if (this.options.maxKeys > -1 && this.stats.keys >= this.options.maxKeys) {
|
|||
|
_err = this._error("ECACHEFULL");
|
|||
|
throw _err;
|
|||
|
}
|
|||
|
// force the data to string
|
|||
|
if (this.options.forceString && !typeof value === "string") {
|
|||
|
value = JSON.stringify(value);
|
|||
|
}
|
|||
|
// set default ttl if not passed
|
|||
|
if (ttl == null) {
|
|||
|
ttl = this.options.stdTTL;
|
|||
|
}
|
|||
|
// handle invalid key types
|
|||
|
if ((err = this._isInvalidKey(key)) != null) {
|
|||
|
throw err;
|
|||
|
}
|
|||
|
// internal helper variables
|
|||
|
existent = false;
|
|||
|
// remove existing data from stats
|
|||
|
if (this.data[key]) {
|
|||
|
existent = true;
|
|||
|
this.stats.vsize -= this._getValLength(this._unwrap(this.data[key], false));
|
|||
|
}
|
|||
|
// set the value
|
|||
|
this.data[key] = this._wrap(value, ttl);
|
|||
|
this.stats.vsize += this._getValLength(value);
|
|||
|
// only add the keys and key-size if the key is new
|
|||
|
if (!existent) {
|
|||
|
this.stats.ksize += this._getKeyLength(key);
|
|||
|
this.stats.keys++;
|
|||
|
}
|
|||
|
this.emit("set", key, value);
|
|||
|
// return true
|
|||
|
return true;
|
|||
|
}
|
|||
|
|
|||
|
mset(keyValueSet) {
|
|||
|
var _err, err, i, j, key, keyValuePair, len, len1, ttl, val;
|
|||
|
boundMethodCheck(this, NodeCache);
|
|||
|
// check if cache is overflowing
|
|||
|
if (this.options.maxKeys > -1 && this.stats.keys + keyValueSet.length >= this.options.maxKeys) {
|
|||
|
_err = this._error("ECACHEFULL");
|
|||
|
throw _err;
|
|||
|
}
|
|||
|
|
|||
|
// loop over keyValueSet to validate key and ttl
|
|||
|
for (i = 0, len = keyValueSet.length; i < len; i++) {
|
|||
|
keyValuePair = keyValueSet[i];
|
|||
|
({key, val, ttl} = keyValuePair);
|
|||
|
// check if there is ttl and it's a number
|
|||
|
if (ttl && typeof ttl !== "number") {
|
|||
|
_err = this._error("ETTLTYPE");
|
|||
|
throw _err;
|
|||
|
}
|
|||
|
// handle invalid key types
|
|||
|
if ((err = this._isInvalidKey(key)) != null) {
|
|||
|
throw err;
|
|||
|
}
|
|||
|
}
|
|||
|
for (j = 0, len1 = keyValueSet.length; j < len1; j++) {
|
|||
|
keyValuePair = keyValueSet[j];
|
|||
|
({key, val, ttl} = keyValuePair);
|
|||
|
this.set(key, val, ttl);
|
|||
|
}
|
|||
|
return true;
|
|||
|
}
|
|||
|
|
|||
|
del(keys) {
|
|||
|
var delCount, err, i, key, len, oldVal;
|
|||
|
boundMethodCheck(this, NodeCache);
|
|||
|
// convert keys to an array of itself
|
|||
|
if (!Array.isArray(keys)) {
|
|||
|
keys = [keys];
|
|||
|
}
|
|||
|
delCount = 0;
|
|||
|
for (i = 0, len = keys.length; i < len; i++) {
|
|||
|
key = keys[i];
|
|||
|
// handle invalid key types
|
|||
|
if ((err = this._isInvalidKey(key)) != null) {
|
|||
|
throw err;
|
|||
|
}
|
|||
|
// only delete if existent
|
|||
|
if (this.data[key] != null) {
|
|||
|
// calc the stats
|
|||
|
this.stats.vsize -= this._getValLength(this._unwrap(this.data[key], false));
|
|||
|
this.stats.ksize -= this._getKeyLength(key);
|
|||
|
this.stats.keys--;
|
|||
|
delCount++;
|
|||
|
// delete the value
|
|||
|
oldVal = this.data[key];
|
|||
|
delete this.data[key];
|
|||
|
// return true
|
|||
|
this.emit("del", key, oldVal.v);
|
|||
|
}
|
|||
|
}
|
|||
|
return delCount;
|
|||
|
}
|
|||
|
|
|||
|
take(key) {
|
|||
|
var _ret;
|
|||
|
boundMethodCheck(this, NodeCache);
|
|||
|
_ret = this.get(key);
|
|||
|
if ((_ret != null)) {
|
|||
|
this.del(key);
|
|||
|
}
|
|||
|
return _ret;
|
|||
|
}
|
|||
|
|
|||
|
ttl(key, ttl) {
|
|||
|
var err;
|
|||
|
boundMethodCheck(this, NodeCache);
|
|||
|
ttl || (ttl = this.options.stdTTL);
|
|||
|
if (!key) {
|
|||
|
return false;
|
|||
|
}
|
|||
|
// handle invalid key types
|
|||
|
if ((err = this._isInvalidKey(key)) != null) {
|
|||
|
throw err;
|
|||
|
}
|
|||
|
// check for existent data and update the ttl value
|
|||
|
if ((this.data[key] != null) && this._check(key, this.data[key])) {
|
|||
|
// if ttl < 0 delete the key. otherwise reset the value
|
|||
|
if (ttl >= 0) {
|
|||
|
this.data[key] = this._wrap(this.data[key].v, ttl, false);
|
|||
|
} else {
|
|||
|
this.del(key);
|
|||
|
}
|
|||
|
return true;
|
|||
|
} else {
|
|||
|
// return false if key has not been found
|
|||
|
return false;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
getTtl(key) {
|
|||
|
var _ttl, err;
|
|||
|
boundMethodCheck(this, NodeCache);
|
|||
|
if (!key) {
|
|||
|
return void 0;
|
|||
|
}
|
|||
|
// handle invalid key types
|
|||
|
if ((err = this._isInvalidKey(key)) != null) {
|
|||
|
throw err;
|
|||
|
}
|
|||
|
// check for existant data and update the ttl value
|
|||
|
if ((this.data[key] != null) && this._check(key, this.data[key])) {
|
|||
|
_ttl = this.data[key].t;
|
|||
|
return _ttl;
|
|||
|
} else {
|
|||
|
// return undefined if key has not been found
|
|||
|
return void 0;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
keys() {
|
|||
|
var _keys;
|
|||
|
boundMethodCheck(this, NodeCache);
|
|||
|
_keys = Object.keys(this.data);
|
|||
|
return _keys;
|
|||
|
}
|
|||
|
|
|||
|
has(key) {
|
|||
|
var _exists;
|
|||
|
boundMethodCheck(this, NodeCache);
|
|||
|
_exists = (this.data[key] != null) && this._check(key, this.data[key]);
|
|||
|
return _exists;
|
|||
|
}
|
|||
|
|
|||
|
getStats() {
|
|||
|
boundMethodCheck(this, NodeCache);
|
|||
|
return this.stats;
|
|||
|
}
|
|||
|
|
|||
|
flushAll(_startPeriod = true) {
|
|||
|
boundMethodCheck(this, NodeCache);
|
|||
|
// parameter just for testing
|
|||
|
|
|||
|
// set data empty
|
|||
|
this.data = {};
|
|||
|
// reset stats
|
|||
|
this.stats = {
|
|||
|
hits: 0,
|
|||
|
misses: 0,
|
|||
|
keys: 0,
|
|||
|
ksize: 0,
|
|||
|
vsize: 0
|
|||
|
};
|
|||
|
// reset check period
|
|||
|
this._killCheckPeriod();
|
|||
|
this._checkData(_startPeriod);
|
|||
|
this.emit("flush");
|
|||
|
}
|
|||
|
|
|||
|
flushStats() {
|
|||
|
boundMethodCheck(this, NodeCache);
|
|||
|
// reset stats
|
|||
|
this.stats = {
|
|||
|
hits: 0,
|
|||
|
misses: 0,
|
|||
|
keys: 0,
|
|||
|
ksize: 0,
|
|||
|
vsize: 0
|
|||
|
};
|
|||
|
this.emit("flush_stats");
|
|||
|
}
|
|||
|
|
|||
|
close() {
|
|||
|
boundMethodCheck(this, NodeCache);
|
|||
|
this._killCheckPeriod();
|
|||
|
}
|
|||
|
|
|||
|
_checkData(startPeriod = true) {
|
|||
|
var key, ref, value;
|
|||
|
boundMethodCheck(this, NodeCache);
|
|||
|
ref = this.data;
|
|||
|
// run the housekeeping method
|
|||
|
for (key in ref) {
|
|||
|
value = ref[key];
|
|||
|
this._check(key, value);
|
|||
|
}
|
|||
|
if (startPeriod && this.options.checkperiod > 0) {
|
|||
|
this.checkTimeout = setTimeout(this._checkData, this.options.checkperiod * 1000, startPeriod);
|
|||
|
if ((this.checkTimeout != null) && (this.checkTimeout.unref != null)) {
|
|||
|
this.checkTimeout.unref();
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// ## _killCheckPeriod
|
|||
|
|
|||
|
// stop the checkdata period. Only needed to abort the script in testing mode.
|
|||
|
_killCheckPeriod() {
|
|||
|
if (this.checkTimeout != null) {
|
|||
|
return clearTimeout(this.checkTimeout);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
_check(key, data) {
|
|||
|
var _retval;
|
|||
|
boundMethodCheck(this, NodeCache);
|
|||
|
_retval = true;
|
|||
|
// data is invalid if the ttl is too old and is not 0
|
|||
|
// console.log data.t < Date.now(), data.t, Date.now()
|
|||
|
if (data.t !== 0 && data.t < Date.now()) {
|
|||
|
if (this.options.deleteOnExpire) {
|
|||
|
_retval = false;
|
|||
|
this.del(key);
|
|||
|
}
|
|||
|
this.emit("expired", key, this._unwrap(data));
|
|||
|
}
|
|||
|
return _retval;
|
|||
|
}
|
|||
|
|
|||
|
_isInvalidKey(key) {
|
|||
|
var ref;
|
|||
|
boundMethodCheck(this, NodeCache);
|
|||
|
if (ref = typeof key, indexOf.call(this.validKeyTypes, ref) < 0) {
|
|||
|
return this._error("EKEYTYPE", {
|
|||
|
type: typeof key
|
|||
|
});
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
_wrap(value, ttl, asClone = true) {
|
|||
|
var livetime, now, oReturn, ttlMultiplicator;
|
|||
|
boundMethodCheck(this, NodeCache);
|
|||
|
if (!this.options.useClones) {
|
|||
|
asClone = false;
|
|||
|
}
|
|||
|
// define the time to live
|
|||
|
now = Date.now();
|
|||
|
livetime = 0;
|
|||
|
ttlMultiplicator = 1000;
|
|||
|
// use given ttl
|
|||
|
if (ttl === 0) {
|
|||
|
livetime = 0;
|
|||
|
} else if (ttl) {
|
|||
|
livetime = now + (ttl * ttlMultiplicator);
|
|||
|
} else {
|
|||
|
// use standard ttl
|
|||
|
if (this.options.stdTTL === 0) {
|
|||
|
livetime = this.options.stdTTL;
|
|||
|
} else {
|
|||
|
livetime = now + (this.options.stdTTL * ttlMultiplicator);
|
|||
|
}
|
|||
|
}
|
|||
|
// return the wrapped value
|
|||
|
return oReturn = {
|
|||
|
t: livetime,
|
|||
|
v: asClone ? clone(value) : value
|
|||
|
};
|
|||
|
}
|
|||
|
|
|||
|
// ## _unwrap
|
|||
|
|
|||
|
// internal method to extract get the value out of the wrapped value
|
|||
|
_unwrap(value, asClone = true) {
|
|||
|
if (!this.options.useClones) {
|
|||
|
asClone = false;
|
|||
|
}
|
|||
|
if (value.v != null) {
|
|||
|
if (asClone) {
|
|||
|
return clone(value.v);
|
|||
|
} else {
|
|||
|
return value.v;
|
|||
|
}
|
|||
|
}
|
|||
|
return null;
|
|||
|
}
|
|||
|
|
|||
|
// ## _getKeyLength
|
|||
|
|
|||
|
// internal method the calculate the key length
|
|||
|
_getKeyLength(key) {
|
|||
|
return key.toString().length;
|
|||
|
}
|
|||
|
|
|||
|
_getValLength(value) {
|
|||
|
boundMethodCheck(this, NodeCache);
|
|||
|
if (typeof value === "string") {
|
|||
|
// if the value is a String get the real length
|
|||
|
return value.length;
|
|||
|
} else if (this.options.forceString) {
|
|||
|
// force string if it's defined and not passed
|
|||
|
return JSON.stringify(value).length;
|
|||
|
} else if (Array.isArray(value)) {
|
|||
|
// if the data is an Array multiply each element with a defined default length
|
|||
|
return this.options.arrayValueSize * value.length;
|
|||
|
} else if (typeof value === "number") {
|
|||
|
return 8;
|
|||
|
} else if (typeof (value != null ? value.then : void 0) === "function") {
|
|||
|
// if the data is a Promise, use defined default
|
|||
|
// (can't calculate actual/resolved value size synchronously)
|
|||
|
return this.options.promiseValueSize;
|
|||
|
} else if (typeof Buffer !== "undefined" && Buffer !== null ? Buffer.isBuffer(value) : void 0) {
|
|||
|
return value.length;
|
|||
|
} else if ((value != null) && typeof value === "object") {
|
|||
|
// if the data is an Object multiply each element with a defined default length
|
|||
|
return this.options.objectValueSize * Object.keys(value).length;
|
|||
|
} else if (typeof value === "boolean") {
|
|||
|
return 8;
|
|||
|
} else {
|
|||
|
// default fallback
|
|||
|
return 0;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
_error(type, data = {}) {
|
|||
|
var error;
|
|||
|
boundMethodCheck(this, NodeCache);
|
|||
|
// generate the error object
|
|||
|
error = new Error();
|
|||
|
error.name = type;
|
|||
|
error.errorcode = type;
|
|||
|
error.message = this.ERRORS[type] != null ? this.ERRORS[type](data) : "-";
|
|||
|
error.data = data;
|
|||
|
// return the error object
|
|||
|
return error;
|
|||
|
}
|
|||
|
|
|||
|
_initErrors() {
|
|||
|
var _errMsg, _errT, ref;
|
|||
|
boundMethodCheck(this, NodeCache);
|
|||
|
this.ERRORS = {};
|
|||
|
ref = this._ERRORS;
|
|||
|
for (_errT in ref) {
|
|||
|
_errMsg = ref[_errT];
|
|||
|
this.ERRORS[_errT] = this.createErrorMessage(_errMsg);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
createErrorMessage(errMsg) {
|
|||
|
return function(args) {
|
|||
|
return errMsg.replace("__key", args.type);
|
|||
|
};
|
|||
|
}
|
|||
|
|
|||
|
};
|
|||
|
|
|||
|
NodeCache.prototype._ERRORS = {
|
|||
|
"ENOTFOUND": "Key `__key` not found",
|
|||
|
"ECACHEFULL": "Cache max keys amount exceeded",
|
|||
|
"EKEYTYPE": "The key argument has to be of type `string` or `number`. Found: `__key`",
|
|||
|
"EKEYSTYPE": "The keys argument has to be an array.",
|
|||
|
"ETTLTYPE": "The ttl argument has to be a number."
|
|||
|
};
|
|||
|
|
|||
|
return NodeCache;
|
|||
|
|
|||
|
}).call(this);
|
|||
|
|
|||
|
}).call(this);
|