From 9c72528908f8693199f189728759fde2b0832dfd Mon Sep 17 00:00:00 2001 From: "Alex A. Naanou" Date: Thu, 17 Dec 2020 18:57:14 +0300 Subject: [PATCH] queue actions seem to be almost done -- still need pretty printing to be pretty ;) Signed-off-by: Alex A. Naanou --- Viewer/features/core.js | 36 +++++++++++------- Viewer/features/examples.js | 33 ++++++++++++---- Viewer/features/sharp.js | 75 ++++++++++++++++++++++++++++++++----- Viewer/package-lock.json | 12 +++--- Viewer/package.json | 4 +- 5 files changed, 122 insertions(+), 38 deletions(-) diff --git a/Viewer/features/core.js b/Viewer/features/core.js index 8cb2b133..007e891c 100755 --- a/Viewer/features/core.js +++ b/Viewer/features/core.js @@ -2650,7 +2650,7 @@ function(title, func){ // -> [items, ...args] // // Prepare args in sync mode... -// arg_handler(undefined, items, ...args) +// arg_handler('sync', items, ...args) // -> [items, ...args] // // @@ -2670,12 +2670,12 @@ function(title, func){ // // This is different from queuedAction(..) in that what is queued is not // the action itself but rather the first argument to that action and the -// action itself is used by the queue to handle each item. The rest of -// the arguments are passed to each call. +// action is used by the queue to handle each item. The rest of the +// arguments are passed to each call. // // In 'sync' mode the action is run outside of queue/task right away, this // is done because for a queue we can only control the sync start, i.e. -// the first task execution, the rest of depends on queue configuration +// the first task execution, the rest depends on queue configuration // thus making the final behaviour unpredictable. // // @@ -2683,6 +2683,12 @@ function(title, func){ // logging is handled by the queue/task which is not created in sync // mode. // NOTE: since the sync-mode can block it must be used very carefully. +// NOTE: for an example of chaining several queues see features/examples's: +// .exampleChainedQueueHandler(..) +// NOTE: when chaining queues, in 'sync' mode all queues in the chain will +// be run sync... +// NOTE: when chaining arg_handler(..) will get one queue per level of +// chaining, but in 'sync' mode only one 'sync' is passed... // // XXX might be a good idea to split this into a generic and domain parts // and move the generic part into types/runner... @@ -2722,8 +2728,11 @@ function(title, func){ items : [items]) .map(function(item){ - return func.call(that, item, ...args) })) } - + var res = func.call(that, item, ...args) + return res === runner.SKIP ? + [] + : [res] }) + .flat()) } // queue mode... } else { // prep queue... @@ -2751,13 +2760,15 @@ function(title, func){ // pre-process args... arg_handler - && (inputs = arg_handler.call(this, q, ...inputs)) + && (inputs = arg_handler.call(this, + sync == 'sync' ? + sync + : q, + ...inputs)) // run... return (inputs instanceof Promise || inputs instanceof runner.FinalizableQueue) ? - // XXX BUG? .then(resolve) is triggered even if inputs was - // stopped (should not resolve) or aborted (should reject)... inputs.then( function(items){ return run([items, ...args]) }, @@ -2768,11 +2779,11 @@ function(title, func){ title, toString: function(){ // XXX add opts of given... - return `core.queueHandler('${action.name}',\n\t${ + return `core.queueHandler('${action.name}',\n${ (arg_handler ? - object.normalizeIndent( '\t'+ arg_handler.toString() ) + ',\n\t' + object.normalizeIndent('\t'+arg_handler.toString()).indent('\t') + ',\n' : '') - + object.normalizeIndent( '\t'+ func.toString() ) })` }, + + object.normalizeIndent('\t'+func.toString()).indent('\t') })` }, }) } var sessionQueueHandler = @@ -2789,7 +2800,6 @@ function(title, func){ // XXX add a task manager UI... // XXX might be a good idea to confirm session task stops when loading a // new index... -// XXX do we need to cache the lister props??? var TaskActions = actions.Actions({ // Tasks... diff --git a/Viewer/features/examples.js b/Viewer/features/examples.js index bc6532d7..4d782e95 100755 --- a/Viewer/features/examples.js +++ b/Viewer/features/examples.js @@ -7,6 +7,8 @@ (function(require){ var module={} // make module AMD/node compatible... /*********************************************************************/ +var runner = require('lib/types/runner') + var toggler = require('lib/toggler') var actions = require('lib/actions') var features = require('lib/features') @@ -322,7 +324,7 @@ var ExampleActions = actions.Actions({ function(item, ...args){ console.log('Queue handler action!!', item, ...args) return new Promise(function(resolve){ - setTimeout(resolve, 100) }) })], + setTimeout(function(){ resolve(item) }, 100) }) })], exampleQueueHandlerActionWArgs: ['- Test/', core.queueHandler('Example queue handler with arguments', {quiet: true}, @@ -339,29 +341,44 @@ var ExampleActions = actions.Actions({ function(item, timeout, ...args){ console.log('Queue handler action!!', item, timeout, ...args) return new Promise(function(resolve){ - setTimeout(resolve, timeout || 100) }) })], + setTimeout(function(){ resolve(item) }, timeout || 100) }) })], exampleChainedQueueHandler: ['- Test/', core.queueHandler('Main queue', core.queueHandler('Sub queue', // pre-prepare the inputs (sync)... function(queue, next, items, ...args){ - console.log('### PRE-PREP', items, ...args) + // NOTE: here we will get both the "Sub queue" queue (queue) + // and the "Main queue" queue (next), but when called + // 'sync' no queues are created and only 'sync' is + // passed as first argument... + if(queue == 'sync'){ + var [queue, items, ...args] = arguments } + + console.log('\tPRE-PREP', items, ...args) + return [items, queue, ...args] }, - //return [items, inner_queue, ...args] }, // prepare inputs (async/queue)... function(item, q, ...args){ - console.log('### PREP', q.state, item, ...args) + console.log('\tPREP', item, ...args) + + // abort/stop queue... item == 'abort' && q.abort() - && console.log('### ABORT', q) + && console.log('\t\tABORT', q) item == 'stop' && q.stop() - && console.log('### STOP') + && console.log('\t\tSTOP') + + // skip strings... + if(typeof(item) == typeof('str')){ + console.log('\t\tSKIP', item) + return runner.SKIP } + return item+1 }), // handle inputs (async/queue)... function(item, ...args){ - console.log('### HANDLE', item, ...args) + console.log('\tHANDLE', item, ...args) return item*2 }) ], }) diff --git a/Viewer/features/sharp.js b/Viewer/features/sharp.js index a0407c5e..7bfb8e24 100755 --- a/Viewer/features/sharp.js +++ b/Viewer/features/sharp.js @@ -190,7 +190,7 @@ var SharpActions = actions.Actions({ // XXX revise return values... // XXX make backup name pattern configurable... // XXX CROP ready for crop support... - makeResizedImage: ['- Image/', + _makeResizedImage: ['- Image/', core.doc`Make resized image(s)... .makeResizedImage(gid, size, path[, options]) @@ -393,7 +393,7 @@ var SharpActions = actions.Actions({ // XXX what should we return??? return to }) }) }) })], - _makeResizedImage: ['- Image/', + _makeResizedImage2: ['- Image/', core.doc`Make resized image(s)... .makeResizedImage(gid, size, path[, options]) @@ -619,16 +619,72 @@ var SharpActions = actions.Actions({ // i.e. call the second queue generator when the first one completes... // or in other works chain queues -- essentially this is like // calling .then(..) on a queue but doing it at definition... - makeResizedImage2: ['- Image/', - core.doc` + makeResizedImage: ['- Image/', + core.doc`Make resized image(s)... + + .makeResizedImage(gid, size, path[, options]) + .makeResizedImage(gids, size, path[, options]) + -> promise + + + Image size formats: + 500px - resize to make image's *largest* dimension 500 pixels (default). + 500p - resize to make image's *smallest* dimension 500 pixels. + 500 - same as 500px + + + options format: + { + // output image name / name pattern... + // + // NOTE: for multiple images this should be a pattern and not an + // explicit name... + // NOTE: if not given this defaults to: "%n" + name: null | , + + // image name pattern data... + // + // NOTE: for more info on pattern see: .formatImageName(..) + data: null | { .. }, + + // if true and image is smaller than size enlarge it... + // + // default: null / false + enlarge: null | true, + + // overwrite, backup or skip (default) existing images... + // + // default: null / false + overwrite: null | true | 'backup', + + // if true do not write an image if it's smaller than size... + // + // default: null / false + skipSmaller: null | true, + + // XXX not implemented... + transform: ..., + crop: ..., + + timestamp: ..., + logger: ..., +, } + + + NOTE: all options are optional. + NOTE: this will not overwrite existing images. `, core.queueHandler('Making resized image', // prepare the data for image resizing (session queue)... core.sessionQueueHandler('Gathering image data for resizing', // prepare the input index-dependant data in a fast way... - function(inner_queue, outer_queue, images, size, path, options){ + function(queue, _, images, size, path, options){ + var n = arguments.length - 1 + if(queue == 'sync'){ + n-- + var [queue, images, size, path, options] = arguments } // sanity check... - if(arguments.length < 4){ + if(n < 3){ throw new Error('.makeResizedImage(..): ' +'need at least: images, size and path.') } return [ @@ -653,7 +709,7 @@ var SharpActions = actions.Actions({ // skip non-images... if(!image || !['image', null, undefined] .includes(image.type)){ - return [] } + return runner.SKIP } return [ // source... this.getImagePath(gid), @@ -676,8 +732,9 @@ var SharpActions = actions.Actions({ ] }), // do the actual resizing (global queue)... function([source, to, image], size, _, options={}){ - // XXX handle skipped items -- source, to and image are undefined... - // XXX + // handle skipped items -- source, to and image are undefined... + if(source == null){ + return undefined } // sizing... var fit = diff --git a/Viewer/package-lock.json b/Viewer/package-lock.json index c7b34445..dd466838 100755 --- a/Viewer/package-lock.json +++ b/Viewer/package-lock.json @@ -1204,14 +1204,14 @@ } }, "ig-object": { - "version": "5.4.12", - "resolved": "https://registry.npmjs.org/ig-object/-/ig-object-5.4.12.tgz", - "integrity": "sha512-9kZM80Js9/eTwXN9VXwLDC1wDJ7gIAdYU9GIzb5KJmNcLAMaW+zhgFrwFFMrcSfggUuadgnqSrS41E4XLe8JZw==" + "version": "5.4.13", + "resolved": "https://registry.npmjs.org/ig-object/-/ig-object-5.4.13.tgz", + "integrity": "sha512-6qJjoDWZ4VmXJvga3LoFH7/JmUoOZuGC73iG54hC8uvv8CAOAMTwTpMm4c2kKAeZ+HdA1sHfa1cjSPVbElmUTA==" }, "ig-types": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ig-types/-/ig-types-6.0.1.tgz", - "integrity": "sha512-yaZU07JZO+9lxPGUjxnvRCGAXyAXSqP9ef33eW8912E751RAUyexruPaJkalvJuRJYzMo6rrURk65asWUNGs/g==", + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/ig-types/-/ig-types-6.0.4.tgz", + "integrity": "sha512-6127GzvMz1Ow8Qizbs0vEvMdYsOJR9HVs0By8dQJIYnX2RRAviUStI+E/wwEH/OxHZpkmFHxwZ6xvmC0S7KP3w==", "requires": { "ig-object": "^5.4.12", "object-run": "^1.0.1" diff --git a/Viewer/package.json b/Viewer/package.json index 5e026f90..62188870 100755 --- a/Viewer/package.json +++ b/Viewer/package.json @@ -33,8 +33,8 @@ "ig-actions": "^3.24.24", "ig-argv": "^2.16.3", "ig-features": "^3.4.2", - "ig-object": "^5.4.12", - "ig-types": "^6.0.1", + "ig-object": "^5.4.13", + "ig-types": "^6.0.4", "json5": "^2.1.3", "object-run": "^1.0.1", "requirejs": "^2.3.6",