queue actions seem to be almost done -- still need pretty printing to be pretty ;)

Signed-off-by: Alex A. Naanou <alex.nanou@gmail.com>
This commit is contained in:
Alex A. Naanou 2020-12-17 18:57:14 +03:00
parent 9d17474e3d
commit 9c72528908
5 changed files with 122 additions and 38 deletions

View File

@ -2650,7 +2650,7 @@ function(title, func){
// -> [items, ...args] // -> [items, ...args]
// //
// Prepare args in sync mode... // Prepare args in sync mode...
// arg_handler(undefined, items, ...args) // arg_handler('sync', items, ...args)
// -> [items, ...args] // -> [items, ...args]
// //
// //
@ -2670,12 +2670,12 @@ function(title, func){
// //
// This is different from queuedAction(..) in that what is queued is not // 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 // 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 // action is used by the queue to handle each item. The rest of the
// the arguments are passed to each call. // arguments are passed to each call.
// //
// In 'sync' mode the action is run outside of queue/task right away, this // 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. // 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. // 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 // logging is handled by the queue/task which is not created in sync
// mode. // mode.
// NOTE: since the sync-mode can block it must be used very carefully. // 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 // XXX might be a good idea to split this into a generic and domain parts
// and move the generic part into types/runner... // and move the generic part into types/runner...
@ -2722,8 +2728,11 @@ function(title, func){
items items
: [items]) : [items])
.map(function(item){ .map(function(item){
return func.call(that, item, ...args) })) } var res = func.call(that, item, ...args)
return res === runner.SKIP ?
[]
: [res] })
.flat()) }
// queue mode... // queue mode...
} else { } else {
// prep queue... // prep queue...
@ -2751,13 +2760,15 @@ function(title, func){
// pre-process args... // pre-process args...
arg_handler arg_handler
&& (inputs = arg_handler.call(this, q, ...inputs)) && (inputs = arg_handler.call(this,
sync == 'sync' ?
sync
: q,
...inputs))
// run... // run...
return (inputs instanceof Promise return (inputs instanceof Promise
|| inputs instanceof runner.FinalizableQueue) ? || inputs instanceof runner.FinalizableQueue) ?
// XXX BUG? .then(resolve) is triggered even if inputs was
// stopped (should not resolve) or aborted (should reject)...
inputs.then( inputs.then(
function(items){ function(items){
return run([items, ...args]) }, return run([items, ...args]) },
@ -2768,11 +2779,11 @@ function(title, func){
title, title,
toString: function(){ toString: function(){
// XXX add opts of given... // XXX add opts of given...
return `core.queueHandler('${action.name}',\n\t${ return `core.queueHandler('${action.name}',\n${
(arg_handler ? (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 = var sessionQueueHandler =
@ -2789,7 +2800,6 @@ function(title, func){
// XXX add a task manager UI... // XXX add a task manager UI...
// XXX might be a good idea to confirm session task stops when loading a // XXX might be a good idea to confirm session task stops when loading a
// new index... // new index...
// XXX do we need to cache the lister props???
var TaskActions = actions.Actions({ var TaskActions = actions.Actions({
// Tasks... // Tasks...

View File

@ -7,6 +7,8 @@
(function(require){ var module={} // make module AMD/node compatible... (function(require){ var module={} // make module AMD/node compatible...
/*********************************************************************/ /*********************************************************************/
var runner = require('lib/types/runner')
var toggler = require('lib/toggler') var toggler = require('lib/toggler')
var actions = require('lib/actions') var actions = require('lib/actions')
var features = require('lib/features') var features = require('lib/features')
@ -322,7 +324,7 @@ var ExampleActions = actions.Actions({
function(item, ...args){ function(item, ...args){
console.log('Queue handler action!!', item, ...args) console.log('Queue handler action!!', item, ...args)
return new Promise(function(resolve){ return new Promise(function(resolve){
setTimeout(resolve, 100) }) })], setTimeout(function(){ resolve(item) }, 100) }) })],
exampleQueueHandlerActionWArgs: ['- Test/', exampleQueueHandlerActionWArgs: ['- Test/',
core.queueHandler('Example queue handler with arguments', core.queueHandler('Example queue handler with arguments',
{quiet: true}, {quiet: true},
@ -339,29 +341,44 @@ var ExampleActions = actions.Actions({
function(item, timeout, ...args){ function(item, timeout, ...args){
console.log('Queue handler action!!', item, timeout, ...args) console.log('Queue handler action!!', item, timeout, ...args)
return new Promise(function(resolve){ return new Promise(function(resolve){
setTimeout(resolve, timeout || 100) }) })], setTimeout(function(){ resolve(item) }, timeout || 100) }) })],
exampleChainedQueueHandler: ['- Test/', exampleChainedQueueHandler: ['- Test/',
core.queueHandler('Main queue', core.queueHandler('Main queue',
core.queueHandler('Sub queue', core.queueHandler('Sub queue',
// pre-prepare the inputs (sync)... // pre-prepare the inputs (sync)...
function(queue, next, items, ...args){ 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, queue, ...args] },
//return [items, inner_queue, ...args] },
// prepare inputs (async/queue)... // prepare inputs (async/queue)...
function(item, q, ...args){ function(item, q, ...args){
console.log('### PREP', q.state, item, ...args) console.log('\tPREP', item, ...args)
// abort/stop queue...
item == 'abort' item == 'abort'
&& q.abort() && q.abort()
&& console.log('### ABORT', q) && console.log('\t\tABORT', q)
item == 'stop' item == 'stop'
&& q.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 }), return item+1 }),
// handle inputs (async/queue)... // handle inputs (async/queue)...
function(item, ...args){ function(item, ...args){
console.log('### HANDLE', item, ...args) console.log('\tHANDLE', item, ...args)
return item*2 }) ], return item*2 }) ],
}) })

View File

@ -190,7 +190,7 @@ var SharpActions = actions.Actions({
// XXX revise return values... // XXX revise return values...
// XXX make backup name pattern configurable... // XXX make backup name pattern configurable...
// XXX CROP ready for crop support... // XXX CROP ready for crop support...
makeResizedImage: ['- Image/', _makeResizedImage: ['- Image/',
core.doc`Make resized image(s)... core.doc`Make resized image(s)...
.makeResizedImage(gid, size, path[, options]) .makeResizedImage(gid, size, path[, options])
@ -393,7 +393,7 @@ var SharpActions = actions.Actions({
// XXX what should we return??? // XXX what should we return???
return to }) }) }) })], return to }) }) }) })],
_makeResizedImage: ['- Image/', _makeResizedImage2: ['- Image/',
core.doc`Make resized image(s)... core.doc`Make resized image(s)...
.makeResizedImage(gid, size, path[, options]) .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... // i.e. call the second queue generator when the first one completes...
// or in other works chain queues -- essentially this is like // or in other works chain queues -- essentially this is like
// calling .then(..) on a queue but doing it at definition... // calling .then(..) on a queue but doing it at definition...
makeResizedImage2: ['- Image/', makeResizedImage: ['- Image/',
core.doc` 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 | <str>,
// 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', core.queueHandler('Making resized image',
// prepare the data for image resizing (session queue)... // prepare the data for image resizing (session queue)...
core.sessionQueueHandler('Gathering image data for resizing', core.sessionQueueHandler('Gathering image data for resizing',
// prepare the input index-dependant data in a fast way... // 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... // sanity check...
if(arguments.length < 4){ if(n < 3){
throw new Error('.makeResizedImage(..): ' throw new Error('.makeResizedImage(..): '
+'need at least: images, size and path.') } +'need at least: images, size and path.') }
return [ return [
@ -653,7 +709,7 @@ var SharpActions = actions.Actions({
// skip non-images... // skip non-images...
if(!image || !['image', null, undefined] if(!image || !['image', null, undefined]
.includes(image.type)){ .includes(image.type)){
return [] } return runner.SKIP }
return [ return [
// source... // source...
this.getImagePath(gid), this.getImagePath(gid),
@ -676,8 +732,9 @@ var SharpActions = actions.Actions({
] }), ] }),
// do the actual resizing (global queue)... // do the actual resizing (global queue)...
function([source, to, image], size, _, options={}){ function([source, to, image], size, _, options={}){
// XXX handle skipped items -- source, to and image are undefined... // handle skipped items -- source, to and image are undefined...
// XXX if(source == null){
return undefined }
// sizing... // sizing...
var fit = var fit =

View File

@ -1204,14 +1204,14 @@
} }
}, },
"ig-object": { "ig-object": {
"version": "5.4.12", "version": "5.4.13",
"resolved": "https://registry.npmjs.org/ig-object/-/ig-object-5.4.12.tgz", "resolved": "https://registry.npmjs.org/ig-object/-/ig-object-5.4.13.tgz",
"integrity": "sha512-9kZM80Js9/eTwXN9VXwLDC1wDJ7gIAdYU9GIzb5KJmNcLAMaW+zhgFrwFFMrcSfggUuadgnqSrS41E4XLe8JZw==" "integrity": "sha512-6qJjoDWZ4VmXJvga3LoFH7/JmUoOZuGC73iG54hC8uvv8CAOAMTwTpMm4c2kKAeZ+HdA1sHfa1cjSPVbElmUTA=="
}, },
"ig-types": { "ig-types": {
"version": "6.0.1", "version": "6.0.4",
"resolved": "https://registry.npmjs.org/ig-types/-/ig-types-6.0.1.tgz", "resolved": "https://registry.npmjs.org/ig-types/-/ig-types-6.0.4.tgz",
"integrity": "sha512-yaZU07JZO+9lxPGUjxnvRCGAXyAXSqP9ef33eW8912E751RAUyexruPaJkalvJuRJYzMo6rrURk65asWUNGs/g==", "integrity": "sha512-6127GzvMz1Ow8Qizbs0vEvMdYsOJR9HVs0By8dQJIYnX2RRAviUStI+E/wwEH/OxHZpkmFHxwZ6xvmC0S7KP3w==",
"requires": { "requires": {
"ig-object": "^5.4.12", "ig-object": "^5.4.12",
"object-run": "^1.0.1" "object-run": "^1.0.1"

View File

@ -33,8 +33,8 @@
"ig-actions": "^3.24.24", "ig-actions": "^3.24.24",
"ig-argv": "^2.16.3", "ig-argv": "^2.16.3",
"ig-features": "^3.4.2", "ig-features": "^3.4.2",
"ig-object": "^5.4.12", "ig-object": "^5.4.13",
"ig-types": "^6.0.1", "ig-types": "^6.0.4",
"json5": "^2.1.3", "json5": "^2.1.3",
"object-run": "^1.0.1", "object-run": "^1.0.1",
"requirejs": "^2.3.6", "requirejs": "^2.3.6",