cordova-app-loader
cordova-app-loader copied to clipboard
Fall back to last working version
Hey :)
If an update fails, why not fall back to the last working version, instead of the bundled version? Wouldn't that be way better?
Yes and no!
Yes: it would be WAY better because users don't fall back many versions. No: In order to do this safely, we need to "backup" the entire app. This effectively doubles the size of your app in your storage.
As for practical implementation, this would be an idea:
- Before update: Copy current app files to backup location. Store current manifest as
backup_manifest - On bootstrap: Check localStorage:
- Is there localStorage
manifest? If yes, use that. - Is there localStorage
backup_manifest? If yes, use that. Save asmanifestin localStorage. - Else, download Manifest.json
- Is there localStorage
I am open for Pull Request. If more people like it, I might implement it myself in the future (I am quite busy doing paid work at the moment)
I am looking into this.
yay!
+1
+1
I'm finally starting on this, but is anyone around for some questions?
Ok, if I can get some feedback that would be great.
What I figured to do was separate the download process from the update process. That way we don't touch the existing configuration/manifest if the download fails. To do that, I thought to create a separate cache for the download step:
this.cache = new CordovaFileCache(options);
this.downloadCache = new CordovaFileCache({
fs: options.fs,
retry: options.retry,
cacheBuster: options.cacheBuster,
serverRoot: options.serverRoot,
localRoot: options.localRoot + "-dwnld"
});
then, in AppLoader.prototype.download we use that downloadCache to get the files:
self.downloadCache.add(self._toBeDownloaded);
return self.downloadCache.download(onprogress)
.then(function() {
self._updateReady = true;
});
and finally, in AppLoader.prototype.update, we finalize the process by deleting and copying files, including from the download cache to the live cache:
if(this._updateReady) {
// update manifest
localStorage.setItem('manifest',JSON.stringify(this.newManifest));
return self.cache.remove(self._toBeDeleted,true)
.then(function(){
return Promise.all(self._toBeCopied.map(function(file){
return self.cache._fs.download(BUNDLE_ROOT + file,self.cache.localRoot + file);
}));
})
.then(function() {
return Promise.all(self.downloadCache.list(),self._toBeDownloaded.map(function(file){
var srcPath = self.downloadCache.toPath(file);
var destPath = self.cache.toPath(file);
return self.downloadCache._fs.read(srcPath)
.then(function(fileContents) {
return self.cache._fs.write(destPath, fileContents);
});
}));
})
.then(function(){
self._toBeDeleted = [];
self._toBeDownloaded = [];
if(reload !== false) location.reload();
return self.newManifest;
});
}
Anyone see an issue here? Mark, am I moving files from one cache to the other correctly?
anyone?