UNPKG

angular.js-server-ng-cache

Version:

A REST API and template caching for server side rendering with angular.js-server

220 lines (175 loc) 6.41 kB
export function $CacheFactoryProvider() { var caches = {}; this.getCaches = function() { return caches; }; this.export = function(cacheId) { if (typeof cache[cacheId] === 'undefined') { throw new Error('$cacheFactory - iid - CacheId '+cacheId+' is not defined!'); } return caches[cacheId].export(); }; this.exportAll = function() { var _caches = {}; for(var i in caches) { _caches[i] = caches[i].export(); } return _caches; }; this.remove = function(cacheId) { if (typeof caches[cacheId] !== 'undefined') { delete caches[cacheId]; } }; this.removeAll = function() { caches = {}; }; this.importAll = function(cacheData) { var cacheFactory = this.$get(); for(var i in cacheData) { if(typeof caches[i] === 'undefined') { caches[i] = cacheFactory(i); } caches[i].import(cacheData[i]); } }; this.import = function(cacheId, cacheData) { var cacheFactory = this.$get(); if(typeof caches[cacheId] === 'undefined') { caches[cacheId] = cacheFactory(i); } caches[cacheId].import(cacheData); }; this.info = function(cacheId) { if(typeof caches[cacheId] === 'undefined') { throw new Error('$cacheFactory - iid - CacheId '+cacheId+' is not defined!'); } return caches[cacheId].info(); }; this.infoAll = function() { var info = {}; for (var cacheId in caches) { info[cacheId] = caches[cacheId].info(); } return info; }; this.$get = function() { function cacheFactory(cacheId, options) { if (cacheId in caches) { return caches[cacheId]; throw new Error('$cacheFactory - iid - CacheId '+cacheId+' is already taken!'); } var size = 0, stats = Object.assign({}, options, {id: cacheId}), data = Object.create(null), capacity = (options && options.capacity) || Number.MAX_VALUE, lruHash = Object.create(null), freshEnd = null, staleEnd = null; return caches[cacheId] = { put: function(key, value) { if ( typeof value === 'undefined') return; if (capacity < Number.MAX_VALUE) { var lruEntry = lruHash[key] || (lruHash[key] = {key: key}); refresh(lruEntry); } if (!(key in data)) size++; data[key] = value; if (size > capacity) { this.remove(staleEnd.key); } return value; }, export: function() { return data; }, import: function(data) { size = 0; lruHash = Object.create(null); freshEnd = null; staleEnd = null; for(var i in data) { this.put(i, data[i]); } }, get: function(key) { if (capacity < Number.MAX_VALUE) { var lruEntry = lruHash[key]; if (!lruEntry) return; refresh(lruEntry); } return data[key]; }, remove: function(key) { if (capacity < Number.MAX_VALUE) { var lruEntry = lruHash[key]; if (!lruEntry) return; if (lruEntry === freshEnd) freshEnd = lruEntry.p; if (lruEntry === staleEnd) staleEnd = lruEntry.n; link(lruEntry.n,lruEntry.p); delete lruHash[key]; } if (!(key in data)) return; delete data[key]; size--; }, removeAll: function() { data = Object.create(null); size = 0; lruHash = Object.create(null); freshEnd = staleEnd = null; }, destroy: function() { data = null; stats = null; lruHash = null; delete caches[cacheId]; }, info: function() { return Object.assign({}, stats, {size: size}); }, keys: function() { return Object.getOwnPropertyNames(data); } }; /** * makes the `entry` the freshEnd of the LRU linked list */ function refresh(entry) { if (entry !== freshEnd) { if (!staleEnd) { staleEnd = entry; } else if (staleEnd === entry) { staleEnd = entry.n; } link(entry.n, entry.p); link(entry, freshEnd); freshEnd = entry; freshEnd.n = null; } } /** * bidirectionally links two entries of the LRU linked list */ function link(nextEntry, prevEntry) { if (nextEntry !== prevEntry) { if (nextEntry) nextEntry.p = prevEntry; //p stands for previous, 'prev' didn't minify if (prevEntry) prevEntry.n = nextEntry; //n stands for next, 'next' didn't minify } } } cacheFactory.info = function() { var info = {}; for (var cacheId in caches) { info[cacheId] = caches[cacheId].info(); } return info; }; return cacheFactory; }; } export function $TemplateCacheProvider(){ this.$get = ['$cacheFactory', function($cacheFactory) { return $cacheFactory('templates'); }]; }