diff --git a/code/data_cache.js b/code/data_cache.js index f7c2c443..2cf72cfc 100644 --- a/code/data_cache.js +++ b/code/data_cache.js @@ -4,17 +4,22 @@ window.DataCache = function() { this.REQUEST_CACHE_FRESH_AGE = 3*60; // if younger than this, use data in the cache rather than fetching from the server - this.REQUEST_CACHE_MAX_AGE = 15*60; // maximum cache age. entries are deleted from the cache after this time + this.REQUEST_CACHE_MAX_AGE = 5*60; // maximum cache age. entries are deleted from the cache after this time + //NOTE: characters are 16 bits (ECMAScript standard), so divide byte size by two for correct limit if (L.Browser.mobile) { // on mobile devices, smaller cache size - this.REQUEST_CACHE_MAX_SIZE = 300; // if more than this many entries, expire early + this.REQUEST_CACHE_MAX_ITEMS = 300; // if more than this many entries, expire early + this.REQUEST_CACHE_MAX_CHARS = 5000000/2; // or more than this total size } else { // but on desktop, allow more - this.REQUEST_CACHE_MAX_SIZE = 1000; // if more than this many entries, expire early + this.REQUEST_CACHE_MAX_ITEMS = 1000; // if more than this many entries, expire early + this.REQUEST_CACHE_MAX_CHARS = 20000000/2; // or more than this total size } this._cache = {}; + this._cacheCharSize = 0; + this._interval = undefined; } @@ -24,18 +29,29 @@ window.DataCache.prototype.store = function(qk,data,freshTime) { // this is handy, as it allows easy retrieval of the oldest entries for expiring // however, this is not guaranteed by the standards, but all our supported browsers work this way - delete this._cache[qk]; + this.remove(qk); var time = new Date().getTime(); if (freshTime===undefined) freshTime = this.REQUEST_CACHE_FRESH_AGE*1000; var expire = time + freshTime; - this._cache[qk] = { time: time, expire: expire, data: JSON.stringify(data) }; + var dataStr = JSON.stringify(data); + + this._cacheCharSize += dataStr.length; + this._cache[qk] = { time: time, expire: expire, dataStr: dataStr }; } +window.DataCache.prototype.remove = function(qk) { + if (qk in this._cache) { + this._cacheCharSize -= this._cache[qk].dataStr.length; + delete this._cache[qk]; + } +} + + window.DataCache.prototype.get = function(qk) { - if (qk in this._cache) return JSON.parse(this._cache[qk].data); + if (qk in this._cache) return JSON.parse(this._cache[qk].dataStr); else return undefined; } @@ -82,9 +98,16 @@ window.DataCache.prototype.runExpire = function() { // fixme? our MAX_SIZE test here assumes we're processing the oldest first. this relies // on looping over object properties in the order they were added. this is true in most browsers, // but is not a requirement of the standards - if (cacheSize > this.REQUEST_CACHE_MAX_SIZE || this._cache[qk].time < t) { + if (cacheSize > this.REQUEST_CACHE_MAX_ITEMS || this._cacheCharSize > this.REQUEST_CACHE_MAX_CHARS || this._cache[qk].time < t) { + this._cacheCharSize -= this._cache[qk].dataStr.length; delete this._cache[qk]; cacheSize--; } } } + + +window.DataCache.prototype.debug = function() { +//NOTE: ECMAScript strings use 16 bit chars (it's in the standard), so convert for bytes/Kb + return 'Cache: '+Object.keys(this._cache).length+' items, '+(this._cacheCharSize*2).toLocaleString()+' bytes ('+Math.ceil(this._cacheCharSize/512).toLocaleString()+'K)'; +}