cache the map data tiles for a short time. this can vastly reduce our load on the niantic servers, especially in the case of multiple repeated scroll/zoom actions in the same area

This commit is contained in:
Jon Atkins 2013-06-15 05:34:23 +01:00
parent ea46405cd9
commit 985bf78e47

View File

@ -5,6 +5,51 @@
// action.
// cache for data tiles. indexed by the query key (qk)
window._requestCache = {}
// cache entries older than the fresh age, and younger than the max age, are stale. they're used in the case of an error from the server
window.REQUEST_CACHE_FRESH_AGE = window.REFRESH; // if younger than this, use data in the cache rather than fetching from the server
window.REQUEST_CACHE_MAX_AGE = 5*window.REFRESH; // maximum cache age. entries are deleted from the cache after this time
window.storeDataCache = function(qk,data) {
var d = new Date();
window._requestCache[qk] = { time: d.getTime(), data: data };
}
window.getDataCache = function(qk) {
if (qk in window._requestCache) {
return window._requestCache[qk].data;
}
return undefined;
}
window.isDataCacheFresh = function(qk) {
if (qk in window._requestCache) {
var d = new Date();
var t = d.getTime()-REQUEST_CACHE_FRESH_AGE*1000;
if (window._requestCache[qk].time > t) {
return true;
}
}
return false;
}
window.expireDataCache = function() {
// TODO: add a limit on the maximum number of cache entries, and start expiring them sooner than the expiry time
// (might also make sense to approximate the size of cache entries, and have an overall size limit?)
var d = new Date();
var t = d.getTime()-window.REQUEST_CACHE_MAX_AGE*1000;
for(var qk in window._requestCache) {
if (window._requestCache[qk].time < t) {
delete window._requestCache[qk];
}
}
}
// requests map data for current viewport. For details on how this
// works, refer to the description in “MAP DATA REQUEST CALCULATORS”
window.requestData = function() {
@ -12,6 +57,8 @@ window.requestData = function() {
requests.abort();
cleanUp();
expireDataCache();
//a limit on the number of map tiles to be pulled in a single request
var MAX_TILES_PER_BUCKET = 20;
@ -29,10 +76,16 @@ window.requestData = function() {
tiles = {};
fullBucketCount = 0;
var cachedData = { result: { map: {} } };
var requestTileCount = 0;
// walk in x-direction, starts right goes left
for (var x = x1; x <= x2; x++) {
for (var y = y1; y <= y2; y++) {
var tile_id = pointToTileId(z, x, y);
if (isDataCacheFresh(tile_id)) {
cachedData.result.map[tile_id] = getDataCache(tile_id);
} else {
var bucket = (Math.floor(x/2) % 2) + ":" + (Math.floor(y/2) % 2);
if (!tiles[bucket]) {
//create empty bucket
@ -45,6 +98,7 @@ window.requestData = function() {
tiles[bucket] = [];
}
requestTileCount++;
tiles[bucket].push(generateBoundsParams(
tile_id,
tileToLat(y + 1, z),
@ -54,15 +108,21 @@ window.requestData = function() {
));
}
}
}
// Reset previous result of Portal Render Limit handler
portalRenderLimit.init();
// process the requests from the cache
console.log('got '+Object.keys(cachedData.result.map).length+' data tiles from cache');
handleDataResponse(cachedData, true);
// finally send ajax requests
console.log('requesting '+requestTileCount+' tiles in '+Object.keys(tiles).length+' requests');
$.each(tiles, function(ind, tls) {
data = { zoom: z };
data.boundsParamsList = tls;
window.requests.add(window.postAjax('getThinnedEntitiesV2', data, window.handleDataResponse, window.handleFailedRequest));
window.requests.add(window.postAjax('getThinnedEntitiesV2', data, function(data, textStatus, jqXHR) { window.handleDataResponse(data,false); }, window.handleFailedRequest));
});
}
@ -76,7 +136,7 @@ window.handleFailedRequest = function() {
}
// works on map data response and ensures entities are drawn/updated.
window.handleDataResponse = function(data, textStatus, jqXHR) {
window.handleDataResponse = function(data, fromCache) {
// remove from active ajax queries list
if(!data || !data.result) {
window.failedRequestCount++;
@ -96,7 +156,19 @@ window.handleDataResponse = function(data, textStatus, jqXHR) {
$.each(m, function(qk, val) {
if('error' in val) {
console.log('map data tile '+qk+' response error: '+val.error);
// try to use data in the cache, even if it's stale
val = getDataCache(qk);
if (!val) {
// no data in cache for this tile - skip it
return true; // $.each 'continue'
} else {
console.log('(using stale cache entry for map tile)');
}
}
if (!fromCache) storeDataCache(qk,val);
$.each(val.deletedGameEntityGuids || [], function(ind, guid) {
if(getTypeByGuid(guid) === TYPE_FIELD && window.fields[guid] !== undefined) {