added cache clean code
This commit is contained in:
parent
2010e420d8
commit
e9c8d1a45a
|
@ -92,7 +92,7 @@ A javascript library providing server defined loading of assets for a single pag
|
|||
* server.question.title = The question ui title. (default: 'Server')
|
||||
* server.question.text = The question ui text. (default: 'Please provide the server name;')
|
||||
* server.question.style = The question ui css style.(note: pending change) (default: green border box)
|
||||
* cache.meta = The cache backend for the meta information, null is auto select. (default: null)
|
||||
* cache.meta = The cache backend for the meta information(server.url+content), null is auto select. (default: null)
|
||||
* cache.js = The cache backend for for js, null is auto select. (default: null)
|
||||
* cache.css = The cache backend for for css, null is auto select. (default: null)
|
||||
* cache.cssData = The cache backend for for cssData, null is auto select. (default: null)
|
||||
|
@ -121,7 +121,7 @@ A javascript library providing server defined loading of assets for a single pag
|
|||
|
||||
More custom schemas are possible like; (todo: needs testing)
|
||||
|
||||
FFSpaLoader.options.cache.meta = null; // use auto -> TODO: currently other cached need meta needs fixing.
|
||||
FFSpaLoader.options.cache.meta = false;
|
||||
FFSpaLoader.options.cache.js = false;
|
||||
FFSpaLoader.options.cache.css = false;
|
||||
FFSpaLoader.options.cache.cssData = false;
|
||||
|
@ -148,7 +148,6 @@ A javascript library providing server defined loading of assets for a single pag
|
|||
|
||||
## Todo
|
||||
|
||||
* Auto cache cleanup code. (!! required before production !!)
|
||||
* test in production
|
||||
* Server header set+check support
|
||||
* Redo css(?divs) of server question
|
||||
|
@ -166,9 +165,10 @@ Add unit tests for any new or changed functionality. Lint and test your code.
|
|||
## Release History
|
||||
|
||||
### 0.0.4
|
||||
* Added auto cache clean code
|
||||
* Disable cordova timeout per default.
|
||||
* Remove unused mobileAgent detect.
|
||||
* Fixed cached resources loading.
|
||||
* Fixed cached resources injection order.
|
||||
|
||||
|
||||
### 0.0.3
|
||||
|
|
|
@ -159,6 +159,7 @@
|
|||
};
|
||||
};
|
||||
var executeSql = function(tx, query, values, resultHandler, errorHandler) {
|
||||
utilDebug('websql.executeSql '+query);
|
||||
tx.executeSql(query, values, resultHandler, function(tx,err) {
|
||||
errorHandler(new Error('Code: '+err.code+' '+err.message+' by query: '+query));
|
||||
});
|
||||
|
@ -166,11 +167,8 @@
|
|||
var cacheDBInit = function(cb) {
|
||||
cacheDB.transaction(function(tx) {
|
||||
var query = 'CREATE TABLE cache_store(id INTEGER PRIMARY KEY AUTOINCREMENT, key TEXT NOT NULL, value TEXT NOT NULL)';
|
||||
utilDebug('websql.init query '+query);
|
||||
executeSql(tx, query, [], function(tx) {
|
||||
var query = 'CREATE UNIQUE INDEX cache_store__key__udx ON cache_store (key)';
|
||||
utilDebug('websql.init query '+query);
|
||||
executeSql(tx, query, [], nullDataHandler(cb), cb);
|
||||
executeSql(tx, 'CREATE UNIQUE INDEX cache_store__key__udx ON cache_store (key)', [], nullDataHandler(cb), cb);
|
||||
}, cb);
|
||||
});
|
||||
};
|
||||
|
@ -185,9 +183,7 @@
|
|||
return cb(e);
|
||||
}
|
||||
cacheDB.transaction(function(tx) {
|
||||
var query = 'SELECT value FROM cache_store WHERE key = \"test-for-table\"';
|
||||
utilDebug('websql.cacheOpen query '+query);
|
||||
executeSql(tx, query, [], function() {
|
||||
executeSql(tx,'SELECT value FROM cache_store WHERE key = \"test-for-table\"', [], function() {
|
||||
cb(null);
|
||||
}, function() {
|
||||
cacheDBInit(cb);
|
||||
|
@ -196,9 +192,7 @@
|
|||
},
|
||||
cacheGetValue: function(key, cb) {
|
||||
cacheDB.transaction(function(tx) {
|
||||
var query = 'SELECT value FROM cache_store WHERE key = ?';
|
||||
utilDebug('websql.cacheGetValue query '+query);
|
||||
executeSql(tx, query,[key], function(tx, res) {
|
||||
executeSql(tx, 'SELECT value FROM cache_store WHERE key = ?',[key], function(tx, res) {
|
||||
if (res.rows.length === 0) {
|
||||
cb(null, null);
|
||||
} else {
|
||||
|
@ -210,16 +204,12 @@
|
|||
},
|
||||
cacheSetValue: function(key, value, cb) {
|
||||
cacheDB.transaction(function(tx) {
|
||||
var query = 'SELECT value FROM cache_store WHERE key = ?';
|
||||
utilDebug('websql.cacheSetValue query '+query);
|
||||
executeSql(tx, query,[key], function(tx, res) {
|
||||
executeSql(tx, 'SELECT value FROM cache_store WHERE key = ?',[key], function(tx, res) {
|
||||
if (res.rows.length === 0) {
|
||||
var queryInsert = 'INSERT INTO cache_store (key,value) VALUES (?,?)';
|
||||
utilDebug('websql.cacheSetValue query '+queryInsert);
|
||||
executeSql(tx, queryInsert, [key,JSON.stringify(value)], nullDataHandler(cb), cb);
|
||||
} else {
|
||||
var queryUpdate = 'UPDATE cache_store SET value = ? WHERE key = ?';
|
||||
utilDebug('websql.cacheSetValue query '+queryUpdate);
|
||||
executeSql(tx, queryUpdate, [JSON.stringify(value),key], nullDataHandler(cb), cb);
|
||||
}
|
||||
}, cb);
|
||||
|
@ -227,9 +217,7 @@
|
|||
},
|
||||
cacheDeleteValue: function(key, cb) {
|
||||
cacheDB.transaction(function(tx) {
|
||||
var query = 'DELETE FROM cache_store WHERE key = ?';
|
||||
utilDebug('websql.cacheDeleteValue query '+query);
|
||||
executeSql(tx, query, [key], function () {
|
||||
executeSql(tx, 'DELETE FROM cache_store WHERE key = ?', [key], function () {
|
||||
setTimeout(nullDataHandler(cb)); // return next tick so transaction is flushed before location.reload
|
||||
}, cb);
|
||||
});
|
||||
|
@ -282,7 +270,7 @@
|
|||
try {
|
||||
var stack = err.stack || '';
|
||||
stack = stack.split('\n').map(function (line) { return line.trim(); });
|
||||
var stackText = stack.splice(stack[0] == 'Error' ? 2 : 1);
|
||||
var stackText = stack.splice(stack[0] === 'Error' ? 2 : 1);
|
||||
|
||||
var traceTag = document.createElement('div');
|
||||
traceTag.appendChild(document.createTextNode(stackText));
|
||||
|
@ -317,6 +305,26 @@
|
|||
httpRequest.send();
|
||||
};
|
||||
|
||||
var utilRunStack = function(runType, stack, step, cb) {
|
||||
if (stack.length === 0) {
|
||||
return cb(null);
|
||||
}
|
||||
utilDebug(runType);
|
||||
var startTime = new Date().getTime();
|
||||
var runStack = stack;
|
||||
var runStackStep = function(err) {
|
||||
if (err !== null) { return cb(err); }
|
||||
runStack = runStack.slice(1);
|
||||
if (runStack.length === 0) {
|
||||
utilDebug(runType+' done '+stack.length+' in '+(new Date().getTime()-startTime)+' ms.');
|
||||
cb(null);
|
||||
} else {
|
||||
step(runStack[0],runStackStep);
|
||||
}
|
||||
};
|
||||
step(runStack[0],runStackStep);
|
||||
};
|
||||
|
||||
var cacheGetService = function (type) {
|
||||
if (options.cache[type]) {
|
||||
return options.cache[type];
|
||||
|
@ -356,11 +364,64 @@
|
|||
});
|
||||
};
|
||||
|
||||
// var cleanupCache = function (resources, cb) {
|
||||
// utilDebug('cleanupCache TODO cacheList '+0+' resources '+resources.length);
|
||||
// // TODO: impl for removes in resource lists
|
||||
// cb(null);
|
||||
// };
|
||||
var cleanupCache = function (resources, cb) {
|
||||
var typedKeys = {};
|
||||
resources.forEach(function (r) {
|
||||
var typeKey = typedKeys[r.type];
|
||||
if (typeKey === undefined) {
|
||||
typeKey = [];
|
||||
typedKeys[r.type] = typeKey;
|
||||
}
|
||||
typeKey.push(r.hash);
|
||||
});
|
||||
var steps = [];
|
||||
var keys = Object.keys(typedKeys);
|
||||
for (var keyIdx in keys) {
|
||||
var type = keys[keyIdx];
|
||||
if (!cacheHasService(type)) {
|
||||
continue;
|
||||
}
|
||||
steps.push({keys: typedKeys[type], type: type});
|
||||
}
|
||||
utilRunStack('cleanupCacheKeys',steps, function(typeKey, cb) {
|
||||
cacheGetValue(typeKey.type,'keys',function (err,value) {
|
||||
if (err !== null) {
|
||||
return cb(err);
|
||||
}
|
||||
if (value === null) {
|
||||
return cb(null);
|
||||
}
|
||||
var diff = [];
|
||||
for (var i=0;i<value.length;i++) {
|
||||
if (typeKey.keys.indexOf(value[i]) === -1) {
|
||||
diff.push(value[i]);
|
||||
}
|
||||
}
|
||||
var valueNew = value;
|
||||
for (var i2=0;i2<diff.length;i2++) {
|
||||
var keyIdx = valueNew.indexOf(diff[i2]);
|
||||
if (keyIdx !== -1) {
|
||||
valueNew.splice(keyIdx,1);
|
||||
}
|
||||
}
|
||||
//utilDebug('cleanupCache value1: '+JSON.stringify(value));
|
||||
//utilDebug('cleanupCache value2: '+JSON.stringify(valueNew));
|
||||
|
||||
utilRunStack('cleanupCacheItems',diff, function(key, cb) {
|
||||
cacheDeleteValue(typeKey.type,key,cb);
|
||||
}, function(err) {
|
||||
if (err !== null) {
|
||||
return cb(err);
|
||||
}
|
||||
if (diff.length === 0) {
|
||||
cb(null);
|
||||
} else {
|
||||
cacheSetValue(typeKey.type,'keys',valueNew ,cb);
|
||||
}
|
||||
});
|
||||
});
|
||||
}, cb);
|
||||
};
|
||||
|
||||
var injectResourceData = function(resource, data, cb) {
|
||||
utilDebug('injectResourceData resource '+JSON.stringify(resource)+' data '+data.length);
|
||||
|
@ -381,19 +442,23 @@
|
|||
cb(null);
|
||||
};
|
||||
|
||||
/**
|
||||
* Add all cache keys in central list so we can clear the cache item if resources are removed.
|
||||
* @param {Resource} resource The resource object with the type and hash.
|
||||
* @param {function} cb The callback for error and request if ready.
|
||||
* @private
|
||||
*/
|
||||
var storeResourceKey = function (resource, cb) {
|
||||
// Add all cache keys in central list so we can clear the cache item if resources are removed.
|
||||
var cacheKey = resource.type+'_keys';
|
||||
cacheGetValue('meta',cacheKey,function (err,value) { // TODO: move to resource.type
|
||||
var cacheKey = 'keys';
|
||||
cacheGetValue(resource.type,cacheKey,function (err,value) {
|
||||
if (err !== null) {
|
||||
cb(err);
|
||||
return;
|
||||
return cb(err);
|
||||
}
|
||||
if (value === null) {
|
||||
value = [];
|
||||
}
|
||||
value.push(resource.hash);
|
||||
cacheSetValue('meta',cacheKey,value, cb);
|
||||
cacheSetValue(resource.type,cacheKey,value, cb);
|
||||
});
|
||||
};
|
||||
|
||||
|
@ -447,46 +512,6 @@
|
|||
}
|
||||
};
|
||||
|
||||
var loadResources = function(resources, cb) {
|
||||
var startTime = new Date().getTime();
|
||||
utilDebug('loadResources');
|
||||
var resourceStack = resources;
|
||||
var resourceLoader = function(err) {
|
||||
if (err !== null) { return cb(err); }
|
||||
resourceStack = resourceStack.slice(1);
|
||||
if (resourceStack.length === 0) {
|
||||
utilDebug('loadResources done in '+(new Date().getTime()-startTime)+' ms.');
|
||||
cb(null);
|
||||
} else {
|
||||
loadResource(resourceStack[0],resourceLoader);
|
||||
}
|
||||
};
|
||||
loadResource(resourceStack[0],resourceLoader);
|
||||
};
|
||||
|
||||
var injectResource = function(resource, cb) {
|
||||
cacheGetValue(resource.type,resource.hash,function(err,item) {
|
||||
injectResourceData(resource,item.data,cb);
|
||||
});
|
||||
}
|
||||
|
||||
var injectResources = function(resources, cb) {
|
||||
var startTime = new Date().getTime();
|
||||
utilDebug('injectResources');
|
||||
var resourceStack = resources;
|
||||
var resourceLoader = function(err) {
|
||||
if (err !== null) { return cb(err); }
|
||||
resourceStack = resourceStack.slice(1);
|
||||
if (resourceStack.length === 0) {
|
||||
utilDebug('injectResources done in '+(new Date().getTime()-startTime)+' ms.');
|
||||
cb(null);
|
||||
} else {
|
||||
injectResource(resourceStack[0],resourceLoader);
|
||||
}
|
||||
};
|
||||
injectResource(resourceStack[0],resourceLoader);
|
||||
};
|
||||
|
||||
/**
|
||||
* Starts loader by downloading resource list or using cache version to
|
||||
* load/refresh/inject the resources.
|
||||
|
@ -517,7 +542,11 @@
|
|||
} else if (value === null) {
|
||||
cb(new Error('Have no cache of server resouces from '+options.server.url));
|
||||
} else {
|
||||
injectResources(value, cb);
|
||||
utilRunStack('injectResources', value, function(resource, cb) {
|
||||
cacheGetValue(resource.type,resource.hash,function(err,item) {
|
||||
injectResourceData(resource,item.data,cb);
|
||||
});
|
||||
} , cb);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
|
@ -533,10 +562,13 @@
|
|||
if (cacheHasService('meta')) {
|
||||
cacheSetValue('meta','server_resources',resources, function (err) {
|
||||
if (err !== null) { return cb(err); }
|
||||
loadResources(resources, cb);
|
||||
utilRunStack('loadResources', resources, loadResource , function (err) {
|
||||
if (err !== null) { return cb(err); }
|
||||
cleanupCache(resources,cb); // only clean when fetched + cached
|
||||
});
|
||||
});
|
||||
} else {
|
||||
loadResources(resources, cb);
|
||||
utilRunStack('loadResources', resources, loadResource , cb);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue