UNPKG

memory-cache-ttl

Version:

A simple in-memory cache with Time To Live functionality

142 lines (120 loc) 3.58 kB
'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); var _objectSizeof = require('object-sizeof'); var _objectSizeof2 = _interopRequireDefault(_objectSizeof); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } var options = {}; var cache = {}; var ttlQueue = []; var ttlExtend = new Set(); var genExpire = function genExpire(seconds) { var t = new Date(); t.setSeconds(t.getSeconds() + seconds); return t; }; var binarySearch = function binarySearch(value) { var low = 0; var high = ttlQueue.length; while (low < high) { var mid = low + high >>> 1; // eslint-disable-line no-bitwise if (ttlQueue[mid].expires.getTime() < value) low = mid + 1;else high = mid; } return low; }; var addToTTLQueue = function addToTTLQueue(ttl) { ttlQueue = ttlQueue.filter(function (e) { return e.id !== ttl.id; }); ttlQueue.splice(binarySearch(ttl.expires.getTime()), 0, ttl); }; var cleanExpired = function cleanExpired() { if (ttlQueue.length === 0) return; var now = new Date().getTime(); if (ttlQueue[0].expires.getTime() > now) return; var expiredIndex = binarySearch(now); ttlQueue.slice(0, expiredIndex).map(function (ttl) { return delete cache[ttl.id]; }); ttlQueue = ttlQueue.slice(expiredIndex, ttlQueue.length); }; var set = function set(id, value, ttl) { if (!ttl && !options.ttl) throw new Error('Global or local TTL needs to be set'); cache[id] = value; if (ttl) return addToTTLQueue({ id: id, expires: genExpire(ttl) }); addToTTLQueue({ id: id, expires: options.randomize ? genExpire(Math.ceil(Math.random() * options.ttl)) : genExpire(options.ttl) }); }; var check = function check(id) { return id in cache; }; var get = function get(id) { if (options.extendOnHit) ttlExtend.add(id); return cache[id]; }; var del = function del(id) { delete cache[id]; ttlQueue = ttlQueue.filter(function (t) { return t.id !== id; }); }; var flush = function flush() { cache = {}; ttlQueue = []; }; var onInterval = function onInterval() { if (ttlQueue.length === 0) return; ttlQueue.forEach(function (ttl) { options.onInterval(ttl.id).then(function () { var newValue = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : cache[ttl.id]; cache[ttl.id] = newValue; }); }); }; var extendOnHit = function extendOnHit() { if (ttlExtend.size === 0) return; ttlExtend.forEach(function (id) { return set(id, cache[id]); }); ttlExtend = new Set(); }; var runningProcess = void 0; var runTasks = function runTasks() { if (runningProcess) clearInterval(runningProcess); runningProcess = setInterval(function () { if (options.extendOnHit) extendOnHit(); cleanExpired(); if (options.onInterval) onInterval(); }, options.interval * 1000); }; var init = function init() { var o = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : { interval: 1 }; options = o; if (o.onInterval && typeof o.onInterval !== 'function') { throw new Error('onInterval needs to be a Promise/function'); } runTasks(); }; exports.default = { init: init, set: set, get: get, check: check, del: del, flush: flush, __ttlQueue: function __ttlQueue() { return ttlQueue; }, stats: function stats() { return { cacheEntries: Object.keys(cache).length, ttlQueueEntries: ttlQueue.length, ttlExtendEntries: ttlExtend.size, cacheSize: (0, _objectSizeof2.default)(cache) }; } }; module.exports = exports['default'];