in theory, keeping the javascript objects directly in the cache is a good thing. any instances of, for example, portals on the map, will share the data objects with those in the cache, limiting the overheads for cached items in use however, in practice - relatively large and complex data structures for cached data. and as some items expired from the cache may have data in live portals, etc, complex for garbage collection to clean up. strings, on the other hand - one single object to clean, zero references from anything else - the cache is used as an alternative to network requests. therefore the extra time to encode/parse the strings is no real issue - lower memory overheads? it's liekly a single string is more efficient on RAM use, even taking into account that some objects will be both encoded in the string, and duplicated in live entities on the map time will tell if this is better or worse than direct object storage...
91 lines
2.7 KiB
JavaScript
91 lines
2.7 KiB
JavaScript
// MAP DATA CACHE ///////////////////////////////////
|
|
// cache for map data tiles.
|
|
|
|
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
|
|
|
|
if (L.Browser.mobile) {
|
|
// on mobile devices, smaller cache size
|
|
this.REQUEST_CACHE_MAX_SIZE = 300; // if more than this many entries, expire early
|
|
} else {
|
|
// but on desktop, allow more
|
|
this.REQUEST_CACHE_MAX_SIZE = 1000; // if more than this many entries, expire early
|
|
}
|
|
|
|
this._cache = {};
|
|
this._interval = undefined;
|
|
|
|
}
|
|
|
|
window.DataCache.prototype.store = function(qk,data,freshTime) {
|
|
// fixme? common behaviour for objects is that properties are kept in the order they're added
|
|
// 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];
|
|
|
|
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) };
|
|
}
|
|
|
|
window.DataCache.prototype.get = function(qk) {
|
|
if (qk in this._cache) return JSON.parse(this._cache[qk].data);
|
|
else return undefined;
|
|
}
|
|
|
|
window.DataCache.prototype.getTime = function(qk) {
|
|
if (qk in this._cache) return this._cache[qk].time;
|
|
else return 0;
|
|
}
|
|
|
|
window.DataCache.prototype.isFresh = function(qk) {
|
|
if (qk in this._cache) {
|
|
var d = new Date();
|
|
var t = d.getTime();
|
|
if (this._cache[qk].expire >= t) return true;
|
|
else return false;
|
|
}
|
|
|
|
return undefined;
|
|
}
|
|
|
|
window.DataCache.prototype.startExpireInterval = function(period) {
|
|
if (this._interval === undefined) {
|
|
var savedContext = this;
|
|
this._interval = setInterval (function() { savedContext.runExpire(); }, period*1000);
|
|
}
|
|
}
|
|
|
|
window.DataCache.prototype.stopExpireInterval = function() {
|
|
if (this._interval !== undefined) {
|
|
stopInterval (this._interval);
|
|
this._interval = undefined;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
window.DataCache.prototype.runExpire = function() {
|
|
var d = new Date();
|
|
var t = d.getTime()-this.REQUEST_CACHE_MAX_AGE*1000;
|
|
|
|
var cacheSize = Object.keys(this._cache).length;
|
|
|
|
for(var qk in this._cache) {
|
|
|
|
// 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) {
|
|
delete this._cache[qk];
|
|
cacheSize--;
|
|
}
|
|
}
|
|
}
|