added load error recovery mechanism to location feature + cleanup and minor refactoring...

Signed-off-by: Alex A. Naanou <alex.nanou@gmail.com>
This commit is contained in:
Alex A. Naanou 2016-06-04 20:50:37 +03:00
parent 197926a897
commit 9ba18f33ae
4 changed files with 118 additions and 66 deletions

View File

@ -125,10 +125,6 @@ var FileSystemLoaderActions = actions.Actions({
'image-file-read-stat': true, 'image-file-read-stat': true,
'image-file-skip-previews': false, 'image-file-skip-previews': false,
// XXX if true and multiple indexes found, load only the first
// without merging...
'load-first-index-only': false,
}, },
// XXX should this be more general??? // XXX should this be more general???
@ -161,6 +157,8 @@ var FileSystemLoaderActions = actions.Actions({
loadIndex: ['- File/Load index', loadIndex: ['- File/Load index',
function(path, from_date, logger){ function(path, from_date, logger){
var that = this var that = this
// XXX get a logger...
logger = logger || this.logger
if(path == null){ if(path == null){
return return
@ -172,9 +170,6 @@ var FileSystemLoaderActions = actions.Actions({
from_date = null from_date = null
} }
// XXX get a logger...
logger = logger || this.logger
// XXX make this load incrementally (i.e. and EventEmitter // XXX make this load incrementally (i.e. and EventEmitter
// a-la glob).... // a-la glob)....
//file.loadIndex(path, this.config['index-dir'], logger) //file.loadIndex(path, this.config['index-dir'], logger)
@ -231,8 +226,6 @@ var FileSystemLoaderActions = actions.Actions({
// load the first index... // load the first index...
if(index == null){ if(index == null){
// XXX use the logger...
//console.log('LOADING:', k, res)
logger && logger.emit('base index', k, res) logger && logger.emit('base index', k, res)
index = part index = part
@ -252,29 +245,23 @@ var FileSystemLoaderActions = actions.Actions({
} }
loaded.push(k) loaded.push(k)
// XXX do a better merge and remove this...
// ...we either need to lazy-load clustered indexes
// or merge, in both cases base_path should reflet
// the fact that we have multiple indexes...
if(that.config['load-first-index-only']){
break
}
} }
logger && logger.emit('load index', index) logger && logger.emit('load index', index)
that.load(index) // prepare the location data...
var location = {
that.__location = {
path: path, path: path,
loaded: loaded, loaded: loaded,
method: 'loadIndex', method: 'loadIndex',
} }
if(from_date){ if(from_date){
that.__location.from = from_date location.from = from_date
} }
// this is the critical section, after this point we
// are doing the actual loading....
that.recoverableLoad(function(){ that.load(index) }, location)
}) })
}], }],
@ -441,23 +428,11 @@ var FileSystemLoaderActions = actions.Actions({
if(path == null){ if(path == null){
return return
} }
// XXX get a logger...
logger = logger || this.logger logger = logger || this.logger
var that = this var that = this
path = util.normalizePath(path) path = util.normalizePath(path)
// NOTE: we set this before we start the load so as to let
// clients know what we are loading and not force them
// to wait to find out...
// XXX not sure if this is the way to go...
var location =
this.__location = {
path: path,
method: 'loadImages',
}
// get the image list... // get the image list...
return this.getImagesInPath( return this.getImagesInPath(
path, path,
@ -466,15 +441,17 @@ var FileSystemLoaderActions = actions.Actions({
logger) logger)
// load the data... // load the data...
.then(function(imgs){ .then(function(imgs){
that.recoverableLoad(function(){
that.load({ that.load({
images: imgs, images: imgs,
data: data.Data.fromArray(imgs.keys()), data: data.Data.fromArray(imgs.keys()),
}) })
// NOTE: we set it again because .load() does a .clear() }, {
// before it starts loading which clears the .location path: path,
// too... method: 'loadImages',
that.__location = location })
}) })
}], }],
@ -561,8 +538,8 @@ module.FileSystemLoader = core.ImageGridFeatures.Feature({
tag: 'fs-loader', tag: 'fs-loader',
depends: [ depends: [
'fs-info',
'location', 'location',
'fs-info',
'tasks', 'tasks',
], ],
suggested: [ suggested: [
@ -1156,8 +1133,6 @@ module.FileSystemLoaderURLHistory = core.ImageGridFeatures.Feature({
handlers: [ handlers: [
pushToHistory('loadImages'), pushToHistory('loadImages'),
pushToHistory('loadIndex'), pushToHistory('loadIndex'),
pushToHistory('loadPath'),
//pushToHistory('loadNewImages'),
], ],
}) })
@ -1400,18 +1375,27 @@ var FileSystemWriterActions = actions.Actions({
} }
}], }],
// Save index...
//
// Returns:
// a promise, when resolved will get the location object as argument.
//
// NOTE: with no arguments this will save index to .location.path // NOTE: with no arguments this will save index to .location.path
//
// XXX should this return a promise??? ...a clean promise??? // XXX should this return a promise??? ...a clean promise???
// XXX BUG: after .loadImages(..) and without arguments this produces // XXX BUG: after .loadImages(..) and without arguments this produces
// a result that is not loaded.... // a result that is not loaded....
saveIndex: ['- File/', saveIndex: ['- File/',
function(path, logger){ function(path, logger){
var that = this var that = this
// XXX get a logger...
logger = logger || this.logger
path = path || this.location.loaded path = path || this.location.loaded
path = path && path.length == 1 ? path[0] : path path = path && path.length == 1 ? path[0] : path
path = util.normalizePath(path) path = util.normalizePath(path)
// merged index...
// XXX // XXX
if(path instanceof Array){ if(path instanceof Array){
console.error('saving to merged indexes not yet supported...') console.error('saving to merged indexes not yet supported...')
@ -1431,12 +1415,12 @@ var FileSystemWriterActions = actions.Actions({
path = this.location.path +'/'+ path path = this.location.path +'/'+ path
} }
// XXX get a logger...
logger = logger || this.logger
// XXX get real base path... // XXX get real base path...
//path = path || this.location.path +'/'+ this.config['index-dir'] //path = path || this.location.path +'/'+ this.config['index-dir']
// NOTE: this will prevent us from overwriting the location
// after we have loaded something else...
var location = this.location
var index = this.prepareIndexForWrite() var index = this.prepareIndexForWrite()
return file.writeIndex( return file.writeIndex(
@ -1446,10 +1430,12 @@ var FileSystemWriterActions = actions.Actions({
path +'/'+ this.config['index-dir'], path +'/'+ this.config['index-dir'],
index.date, index.date,
this.config['index-filename-template'], this.config['index-filename-template'],
logger || this.logger) logger)
.then(function(){ .then(function(){
that.location.method = 'loadIndex' location.method = 'loadIndex'
that.location.from = index.date location.from = index.date
return location
}) })
}], }],

View File

@ -361,23 +361,25 @@ module.URLHistoryFSWriter = core.ImageGridFeatures.Feature({
handlers: [ handlers: [
['saveIndex', ['saveIndex',
function(){ function(res){
var that = this
res.then(function(l){
// push saved to top... // push saved to top...
if(this.config['url-history-push-to-top-on-save']){ if(that.config['url-history-push-to-top-on-save']){
this.pushURLToHistory() that.pushURLToHistory(l.path, l.method)
// update... // update...
} else { } else {
var l = this.location var e = that.url_history[l.path]
var e = this.url_history[l.path]
if(e != null){ if(e != null){
e.open = l.method e.open = l.method
this.saveURLHistory() that.saveURLHistory()
} else { } else {
this.pushURLToHistory() that.pushURLToHistory(l.path, l.method)
} }
} }
})
}], }],
], ],
}) })

View File

@ -30,6 +30,10 @@ var core = require('features/core')
// .path or .url // .path or .url
var LocationActions = actions.Actions({ var LocationActions = actions.Actions({
config: {
'recover-load-errors-to-previous-location': true,
},
// Format: // Format:
// { // {
// path: <base-path>, // path: <base-path>,
@ -60,6 +64,7 @@ var LocationActions = actions.Actions({
return this.__location return this.__location
}, },
// XXX is 'loadIndex' a good default???
set location(value){ set location(value){
// got a path... // got a path...
if(typeof(value) == typeof('str')){ if(typeof(value) == typeof('str')){
@ -87,6 +92,7 @@ var LocationActions = actions.Actions({
this.__location = value this.__location = value
// XXX is 'loadIndex' a good default???
var res = this[value.method || 'loadIndex'](path) var res = this[value.method || 'loadIndex'](path)
// XXX load current... // XXX load current...
@ -99,6 +105,64 @@ var LocationActions = actions.Actions({
this.current = cur this.current = cur
} }
}, },
// Wrap the loader and recover if it fails...
//
// .recoverableLoad(loader, new-location)
// -> actions
//
// NOTE: this avoids load loops by attempting to recover only once...
//
// XXX should this be used in .location setter?
recoverableLoad: ['- Location/',
function(loader, location){
// this is the critical section, after this point we
// are doing the actual loading....
try {
// prepare to recover, just in case...
this.__recover = (this.__recover !== false
&& this.config['recover-load-errors-to-previous-location']) ?
this.location
: false
loader()
// NOTE: we are setting this after the load because the
// loader may .clear() the viewer, thus clearing the
// .location too...
this.__location = location
// all went well clear the recovery data...
delete this.__recover
// something bad happened, clear and handle it...
} catch(err){
this.clear()
console.error(err)
// recover to last location...
if(this.__recover){
var l = this.__recover
// NOTE: this will prevent us from entering
// a recover attempt loop...
// ...if the recovery fails we will just
// clear and stop.
this.__recover = false
// do the loading...
this.location = l
// fail...
} else {
// clear the recovery data...
delete this.__recover
// fail...
throw err
}
}
}],
}) })
module.Location = core.ImageGridFeatures.Feature({ module.Location = core.ImageGridFeatures.Feature({

View File

@ -662,7 +662,7 @@ module.ImagesPrototype = {
clone: function(){ clone: function(){
return (new Images()).join(this) return (new Images()).loadJSON(this.dumpJSON())
}, },
// NOTE: this will join the other data into the current object in-place, // NOTE: this will join the other data into the current object in-place,
// use .clone() to preserve current data... // use .clone() to preserve current data...