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.title = The question ui title. (default: 'Server')
|
||||||
* server.question.text = The question ui text. (default: 'Please provide the server name;')
|
* 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)
|
* 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.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.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)
|
* 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)
|
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.js = false;
|
||||||
FFSpaLoader.options.cache.css = false;
|
FFSpaLoader.options.cache.css = false;
|
||||||
FFSpaLoader.options.cache.cssData = false;
|
FFSpaLoader.options.cache.cssData = false;
|
||||||
|
@ -148,7 +148,6 @@ A javascript library providing server defined loading of assets for a single pag
|
||||||
|
|
||||||
## Todo
|
## Todo
|
||||||
|
|
||||||
* Auto cache cleanup code. (!! required before production !!)
|
|
||||||
* test in production
|
* test in production
|
||||||
* Server header set+check support
|
* Server header set+check support
|
||||||
* Redo css(?divs) of server question
|
* 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
|
## Release History
|
||||||
|
|
||||||
### 0.0.4
|
### 0.0.4
|
||||||
|
* Added auto cache clean code
|
||||||
* Disable cordova timeout per default.
|
* Disable cordova timeout per default.
|
||||||
* Remove unused mobileAgent detect.
|
* Remove unused mobileAgent detect.
|
||||||
* Fixed cached resources loading.
|
* Fixed cached resources injection order.
|
||||||
|
|
||||||
|
|
||||||
### 0.0.3
|
### 0.0.3
|
||||||
|
|
|
@ -159,6 +159,7 @@
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
var executeSql = function(tx, query, values, resultHandler, errorHandler) {
|
var executeSql = function(tx, query, values, resultHandler, errorHandler) {
|
||||||
|
utilDebug('websql.executeSql '+query);
|
||||||
tx.executeSql(query, values, resultHandler, function(tx,err) {
|
tx.executeSql(query, values, resultHandler, function(tx,err) {
|
||||||
errorHandler(new Error('Code: '+err.code+' '+err.message+' by query: '+query));
|
errorHandler(new Error('Code: '+err.code+' '+err.message+' by query: '+query));
|
||||||
});
|
});
|
||||||
|
@ -166,11 +167,8 @@
|
||||||
var cacheDBInit = function(cb) {
|
var cacheDBInit = function(cb) {
|
||||||
cacheDB.transaction(function(tx) {
|
cacheDB.transaction(function(tx) {
|
||||||
var query = 'CREATE TABLE cache_store(id INTEGER PRIMARY KEY AUTOINCREMENT, key TEXT NOT NULL, value TEXT NOT NULL)';
|
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) {
|
executeSql(tx, query, [], function(tx) {
|
||||||
var query = 'CREATE UNIQUE INDEX cache_store__key__udx ON cache_store (key)';
|
executeSql(tx, 'CREATE UNIQUE INDEX cache_store__key__udx ON cache_store (key)', [], nullDataHandler(cb), cb);
|
||||||
utilDebug('websql.init query '+query);
|
|
||||||
executeSql(tx, query, [], nullDataHandler(cb), cb);
|
|
||||||
}, cb);
|
}, cb);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
@ -185,9 +183,7 @@
|
||||||
return cb(e);
|
return cb(e);
|
||||||
}
|
}
|
||||||
cacheDB.transaction(function(tx) {
|
cacheDB.transaction(function(tx) {
|
||||||
var query = 'SELECT value FROM cache_store WHERE key = \"test-for-table\"';
|
executeSql(tx,'SELECT value FROM cache_store WHERE key = \"test-for-table\"', [], function() {
|
||||||
utilDebug('websql.cacheOpen query '+query);
|
|
||||||
executeSql(tx, query, [], function() {
|
|
||||||
cb(null);
|
cb(null);
|
||||||
}, function() {
|
}, function() {
|
||||||
cacheDBInit(cb);
|
cacheDBInit(cb);
|
||||||
|
@ -196,9 +192,7 @@
|
||||||
},
|
},
|
||||||
cacheGetValue: function(key, cb) {
|
cacheGetValue: function(key, cb) {
|
||||||
cacheDB.transaction(function(tx) {
|
cacheDB.transaction(function(tx) {
|
||||||
var query = 'SELECT value FROM cache_store WHERE key = ?';
|
executeSql(tx, 'SELECT value FROM cache_store WHERE key = ?',[key], function(tx, res) {
|
||||||
utilDebug('websql.cacheGetValue query '+query);
|
|
||||||
executeSql(tx, query,[key], function(tx, res) {
|
|
||||||
if (res.rows.length === 0) {
|
if (res.rows.length === 0) {
|
||||||
cb(null, null);
|
cb(null, null);
|
||||||
} else {
|
} else {
|
||||||
|
@ -210,16 +204,12 @@
|
||||||
},
|
},
|
||||||
cacheSetValue: function(key, value, cb) {
|
cacheSetValue: function(key, value, cb) {
|
||||||
cacheDB.transaction(function(tx) {
|
cacheDB.transaction(function(tx) {
|
||||||
var query = 'SELECT value FROM cache_store WHERE key = ?';
|
executeSql(tx, 'SELECT value FROM cache_store WHERE key = ?',[key], function(tx, res) {
|
||||||
utilDebug('websql.cacheSetValue query '+query);
|
|
||||||
executeSql(tx, query,[key], function(tx, res) {
|
|
||||||
if (res.rows.length === 0) {
|
if (res.rows.length === 0) {
|
||||||
var queryInsert = 'INSERT INTO cache_store (key,value) VALUES (?,?)';
|
var queryInsert = 'INSERT INTO cache_store (key,value) VALUES (?,?)';
|
||||||
utilDebug('websql.cacheSetValue query '+queryInsert);
|
|
||||||
executeSql(tx, queryInsert, [key,JSON.stringify(value)], nullDataHandler(cb), cb);
|
executeSql(tx, queryInsert, [key,JSON.stringify(value)], nullDataHandler(cb), cb);
|
||||||
} else {
|
} else {
|
||||||
var queryUpdate = 'UPDATE cache_store SET value = ? WHERE key = ?';
|
var queryUpdate = 'UPDATE cache_store SET value = ? WHERE key = ?';
|
||||||
utilDebug('websql.cacheSetValue query '+queryUpdate);
|
|
||||||
executeSql(tx, queryUpdate, [JSON.stringify(value),key], nullDataHandler(cb), cb);
|
executeSql(tx, queryUpdate, [JSON.stringify(value),key], nullDataHandler(cb), cb);
|
||||||
}
|
}
|
||||||
}, cb);
|
}, cb);
|
||||||
|
@ -227,9 +217,7 @@
|
||||||
},
|
},
|
||||||
cacheDeleteValue: function(key, cb) {
|
cacheDeleteValue: function(key, cb) {
|
||||||
cacheDB.transaction(function(tx) {
|
cacheDB.transaction(function(tx) {
|
||||||
var query = 'DELETE FROM cache_store WHERE key = ?';
|
executeSql(tx, 'DELETE FROM cache_store WHERE key = ?', [key], function () {
|
||||||
utilDebug('websql.cacheDeleteValue query '+query);
|
|
||||||
executeSql(tx, query, [key], function () {
|
|
||||||
setTimeout(nullDataHandler(cb)); // return next tick so transaction is flushed before location.reload
|
setTimeout(nullDataHandler(cb)); // return next tick so transaction is flushed before location.reload
|
||||||
}, cb);
|
}, cb);
|
||||||
});
|
});
|
||||||
|
@ -282,7 +270,7 @@
|
||||||
try {
|
try {
|
||||||
var stack = err.stack || '';
|
var stack = err.stack || '';
|
||||||
stack = stack.split('\n').map(function (line) { return line.trim(); });
|
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');
|
var traceTag = document.createElement('div');
|
||||||
traceTag.appendChild(document.createTextNode(stackText));
|
traceTag.appendChild(document.createTextNode(stackText));
|
||||||
|
@ -316,6 +304,26 @@
|
||||||
};
|
};
|
||||||
httpRequest.send();
|
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) {
|
var cacheGetService = function (type) {
|
||||||
if (options.cache[type]) {
|
if (options.cache[type]) {
|
||||||
|
@ -356,11 +364,64 @@
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
// var cleanupCache = function (resources, cb) {
|
var cleanupCache = function (resources, cb) {
|
||||||
// utilDebug('cleanupCache TODO cacheList '+0+' resources '+resources.length);
|
var typedKeys = {};
|
||||||
// // TODO: impl for removes in resource lists
|
resources.forEach(function (r) {
|
||||||
// cb(null);
|
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) {
|
var injectResourceData = function(resource, data, cb) {
|
||||||
utilDebug('injectResourceData resource '+JSON.stringify(resource)+' data '+data.length);
|
utilDebug('injectResourceData resource '+JSON.stringify(resource)+' data '+data.length);
|
||||||
|
@ -381,19 +442,23 @@
|
||||||
cb(null);
|
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) {
|
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 = 'keys';
|
||||||
var cacheKey = resource.type+'_keys';
|
cacheGetValue(resource.type,cacheKey,function (err,value) {
|
||||||
cacheGetValue('meta',cacheKey,function (err,value) { // TODO: move to resource.type
|
|
||||||
if (err !== null) {
|
if (err !== null) {
|
||||||
cb(err);
|
return cb(err);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
if (value === null) {
|
if (value === null) {
|
||||||
value = [];
|
value = [];
|
||||||
}
|
}
|
||||||
value.push(resource.hash);
|
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
|
* Starts loader by downloading resource list or using cache version to
|
||||||
* load/refresh/inject the resources.
|
* load/refresh/inject the resources.
|
||||||
|
@ -517,7 +542,11 @@
|
||||||
} else if (value === null) {
|
} else if (value === null) {
|
||||||
cb(new Error('Have no cache of server resouces from '+options.server.url));
|
cb(new Error('Have no cache of server resouces from '+options.server.url));
|
||||||
} else {
|
} 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 {
|
} else {
|
||||||
|
@ -533,10 +562,13 @@
|
||||||
if (cacheHasService('meta')) {
|
if (cacheHasService('meta')) {
|
||||||
cacheSetValue('meta','server_resources',resources, function (err) {
|
cacheSetValue('meta','server_resources',resources, function (err) {
|
||||||
if (err !== null) { return cb(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 {
|
} else {
|
||||||
loadResources(resources, cb);
|
utilRunStack('loadResources', resources, loadResource , cb);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue