qcache
Version:
useful caches: ttl, lru, multi-value
98 lines (85 loc) • 2.67 kB
JavaScript
/**
* qcache -- basic caches
*
* Copyright (C) 2015-2019 Andras Radics
* Licensed under the Apache License, Version 2.0
*
* 2015-01-28 - AR.
*/
'use strict';
module.exports = {
// FIXME: export the class directly, not by name
TtlCache: TtlCache,
// alias
TimeoutCache: TtlCache,
};
var getTimestamp = global.currentTimestamp || require('qtimebase').getTimestamp;
/**
* name-value store with timeout
*/
function TtlCache( options ) {
if (this === global || !this) return new TtlCache(options);
options = options || {};
this.ttl = options.ttl || 31622400000; // 1 year
this.capacity = options.capacity || 10000;
this.count = 0;
this.getTimestamp = options.currentTimestamp || getTimestamp;
this._deleteCount = 0;
this._store = {};
}
TtlCache.prototype = {
getTimestamp: null,
get:
function get( name ) {
var item = this._store[name];
if (item) {
if (item.t >= this.getTimestamp()) return item.v;
else this.delete(name);
}
},
set:
function set( name, value, ttl ) {
ttl = ttl || this.ttl;
// not an lru cache, ok to discard all when capacity exceeded
if (this.count >= this.capacity) { this._store = {}; this.count = 0; }
if (this._store[name] === undefined) this.count += 1;
this._store[name] = { t: this.getTimestamp() + ttl, v: value };
// NOTE: node-v0.10.29 does not run the timer on every ms!
// NOTE: sometimes the qcache timestamp is stale, and returns old values
},
delete:
function delete_( name ) {
if (this._store[name] !== undefined) {
this.count -= 1;
this._store[name] = undefined;
this._deleteCount += 1;
// gc once we can free 1k bytes of deleted slots per live object
if ((this._deleteCount & 0x3FF) === 0 && (this._deleteCount / this.count) > 100 && this.count < 100000) {
this.gc();
this._deleteCount = 0;
}
}
},
keys:
function keys( ) {
return Object.keys(this._store);
},
gc:
function gc( ) {
var ts = this.getTimestamp();
var n = 0, live = {};
for (var i in this._store) {
if (this._store[i] && this._store[i].t >= ts) {
live[i] = this._store[i];
n += 1;
}
}
this._store = live;
this.count = n;
},
};
// aliases
TtlCache.prototype.put = TtlCache.prototype.set;
TtlCache.prototype.del = TtlCache.prototype.delete;
// speed up access
TtlCache.prototype = TtlCache.prototype;