added queues to core.js + .images.iter()...

Signed-off-by: Alex A. Naanou <alex.nanou@gmail.com>
This commit is contained in:
Alex A. Naanou 2020-12-02 03:32:53 +03:00
parent dc1bd9a6f8
commit dfa9693c58
6 changed files with 174 additions and 38 deletions

View File

@ -2484,7 +2484,41 @@ module.Workspace = ImageGridFeatures.Feature({
//---------------------------------------------------------------------
// Tasks...
// Tasks and Queues...
var Queued =
module.Queued =
function(func){
func.__queued__ = true
return func }
// XXX the general use-case here is to call the queue method multiple
// times for instance to handle array elements, might be nice to
// automate this...
// ...would also be nice to automate this via a chunk iterator so
// as not to block...
var queuedAction =
module.queuedAction =
function(name, func){
var args = [...arguments]
func = args.pop()
var [name, opts] = args
return object.mixin(
Queued(function(...args){
var that = this
return this.queue(name, opts || {})
.push(function(){
return func.call(that, ...args) }) }),
{
toString: function(){
return `core.queuedAction('${name}',\n\t${
object.normalizeIndent( '\t'+ func.toString() ) })` },
}) }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Task wrapper...
//
@ -2496,15 +2530,13 @@ function(func){
return func }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Task action action helpers...
// Task action helpers...
//
// NOTE: for examples see:
// features/examples.js:
// ExampleActions.exampleTask(..)
// ExampleActions.exampleSessionTask(..)
//
// NOTE: we can pass sync/async to this in two places, in definition:
// var action = taskAction('some title', 'sync', function(..){ .. })
@ -2557,14 +2589,97 @@ var TaskActions = actions.Actions({
config: {
},
// tests...
// Queue...
//
isQueued: function(action){
return !!this.getActionAttr(action, '__queued__') },
// XXX cache this???
get queuedActions(){
var test = this.isQueued.bind(this)
return this.actions.filter(test) },
// XXX need a way to reference the queue again...
// .tasks.titled(name) will return a list...
// XXX EXPERIMENTAL...
__queues: null,
get queues(){
return (this.__queues = this.__queues || {}) },
// XXX revise signature...
// XXX need better error flow...
queue: doc('Get or create a queue task',
doc`Get or create a queue task...
.queue(name)
.queue(name[, options][, logger])
-> queue
If a queue with the given name already exits it will be returned
and options and logger are ignored.
options format:
{
nonAbortable: <bool>,
quiet: <bool>,
...
}
NOTE: for queue-specific options see ig-types/runner's Queue(..)
`,
function(name, options, logger){
var that = this
var queue = this.queues[name]
// create a new queue...
if(queue == null){
var abort = function(){
options.nonAbortable
|| queue.clear() }
var cleanup = function(){
return function(){
// XXX handle error state...
//logger
// && logger.emit('close')
delete that.queues[name] } }
var logger = logger || this.logger
//logger = logger && logger.push(name)
logger = logger
&& logger.push(name, {onclose: abort, quiet: !!options.quiet})
queue = this.queues[name] =
runner.Queue(options || {})
// setup logging...
if(logger){
queue
.on('tasksAdded', function(evt, t){ logger.emit('added', t) })
.on('taskCompleted', function(evt, t){ logger.emit('done', t) })
.on('taskFailed', function(evt, t, err){ logger.emit('skipped', t, err) })
queue.logger = logger }
// cleanup...
queue
.then(
cleanup('done'),
cleanup('error')) }
// add queue as task...
this.tasks.includes(queue)
|| this.tasks.Task(name, queue)
return queue }),
// Tasks...
//
isTask: function(action){
return !!this.getActionAttr(action, '__task__') },
isSessionTask: function(action){
return !!this.getActionAttr(action, '__session_task__') },
// list actions that generate tasks...
//
// XXX cache these???
get taskActions(){
var test = this.isTask.bind(this)

View File

@ -268,6 +268,17 @@ var ExampleActions = actions.Actions({
// Tasks...
exampleQueuedAction: ['- Test/',
core.queuedAction('exampleQueuedAction', function(timeout=500, ...args){
console.log('Queued action!!', ...args)
return new Promise(function(resolve){
setTimeout(resolve, timeout) }) })],
exampleMultipleQueuedAction: ['- Test/',
function(count=100, timeout=100){
for(var i=0; i<count; i++){
this.exampleQueuedAction(timeout) } }],
//
// NOTE: action name and task name should be the same to avoid
// confusion...

View File

@ -1909,7 +1909,15 @@ var UIIntrospectionActions = actions.Actions({
makeUIDialog(function(actions){
var that = this
actions = actions || this.actions.sort()
actions = actions instanceof Array ? actions : [actions]
actions =
(actions instanceof Array ?
actions
: [actions])
// resolve action objects...
.map(function(action){
return typeof(action) == 'function' ?
action.name
: action })
var doc = this.getDoc(actions)
@ -1949,7 +1957,12 @@ var UIIntrospectionActions = actions.Actions({
// XXX add specific action doc if available....
showCode: ['- Help/Show action code...',
makeUIDialog(function(action){
action = action instanceof Array ? action[0] : action
action = action instanceof Array ?
action[0]
: action
action = typeof(action) == 'function' ?
action.name
: action
var features = this.features.FeatureSet.features
|| this.features.features
|| []

View File

@ -389,12 +389,9 @@ module.ImagesPrototype = {
if(key == 'length'
|| key == 'version'
|| this[key] instanceof Function){
continue
}
func.call(this[key], key, this[key], i++, this)
}
return this
},
continue }
func.call(this[key], key, this[key], i++, this) }
return this },
filter: function(func){
var res = new this.constructor()
var i = 0
@ -404,14 +401,10 @@ module.ImagesPrototype = {
if(key == 'length'
|| key == 'version'
|| this[key] instanceof Function){
continue
}
continue }
if(func.call(this[key], key, this[key], i++, this)){
res[key] = this[key]
}
}
return res
},
res[key] = this[key] } }
return res },
// NOTE: .map(..) and .reduce(..) will not return Images objects...
map: function(func){
//var res = this.constructor()
@ -423,13 +416,10 @@ module.ImagesPrototype = {
if(key == 'length'
|| key == 'version'
|| this[key] instanceof Function){
continue
}
continue }
//res[key] = func.call(this[key], key, this[key], i++, this)
res.push(func.call(this[key], key, this[key], i++, this))
}
return res
},
res.push(func.call(this[key], key, this[key], i++, this)) }
return res },
reduce: function(func, initial){
var res = initial
var i = 0
@ -439,12 +429,19 @@ module.ImagesPrototype = {
if(key == 'length'
|| key == 'version'
|| this[key] instanceof Function){
continue
}
res = func.call(this[key], res, this[key], key, i++, this)
}
return res
},
continue }
res = func.call(this[key], res, this[key], key, i++, this) }
return res },
iter: function*(){
for(var key in this){
// reject non images...
// XXX make this cleaner...
if(key == 'length'
|| key == 'version'
|| this[key] instanceof Function){
continue }
yield [key, this[key]] } },
// XXX remove version...
keys: function(){

View File

@ -1110,9 +1110,9 @@
"integrity": "sha512-9kZM80Js9/eTwXN9VXwLDC1wDJ7gIAdYU9GIzb5KJmNcLAMaW+zhgFrwFFMrcSfggUuadgnqSrS41E4XLe8JZw=="
},
"ig-types": {
"version": "5.0.21",
"resolved": "https://registry.npmjs.org/ig-types/-/ig-types-5.0.21.tgz",
"integrity": "sha512-902m+C7h6/IE6qlD3LzP+fbDstXMEVKltdOgc9YHQWWCK4zI9IgUckp5lJrrDRsZsaDsKAUIUVcYbAfkxKeOdg==",
"version": "5.0.29",
"resolved": "https://registry.npmjs.org/ig-types/-/ig-types-5.0.29.tgz",
"integrity": "sha512-fEHd9qpOz994Meu1dT3cO3N8bwlA6XR7CD608nwM92rjwWSMQcTv5jTULz63eXH1/3otsU4bgWnsjKGDD8zLVw==",
"requires": {
"ig-object": "^5.4.12",
"object-run": "^1.0.1"

View File

@ -32,7 +32,7 @@
"ig-argv": "^2.15.0",
"ig-features": "^3.4.2",
"ig-object": "^5.4.12",
"ig-types": "^5.0.21",
"ig-types": "^5.0.29",
"moment": "^2.29.1",
"object-run": "^1.0.1",
"requirejs": "^2.3.6",