2020-11-07 02:49:32 +03:00
|
|
|
/**********************************************************************
|
|
|
|
|
*
|
|
|
|
|
*
|
|
|
|
|
*
|
2020-11-11 17:39:47 +03:00
|
|
|
*
|
|
|
|
|
* XXX would be helpful to define a task api...
|
2020-11-11 17:47:32 +03:00
|
|
|
* task('abort') vs. task.abort(), task state, ...etc.
|
|
|
|
|
* then define Task and TaskQueue(Queue) and extended api to:
|
|
|
|
|
* - task state introspection
|
|
|
|
|
* - stop/resume tasks (or task queue?)
|
|
|
|
|
* - serialize tasks
|
|
|
|
|
* - ...
|
|
|
|
|
* would be nice to make the task just a slightly extended or better
|
|
|
|
|
* defined function/generator, ideally to make them interchangable...
|
2020-11-11 17:39:47 +03:00
|
|
|
*
|
2020-11-07 02:49:32 +03:00
|
|
|
**********************************************/ /* c8 ignore next 2 */
|
|
|
|
|
((typeof define)[0]=='u'?function(f){module.exports=f(require)}:define)
|
|
|
|
|
(function(require){ var module={} // make module AMD/node compatible...
|
|
|
|
|
/*********************************************************************/
|
|
|
|
|
|
|
|
|
|
var object = require('ig-object')
|
|
|
|
|
|
2020-11-15 00:24:22 +03:00
|
|
|
var events = require('./event')
|
|
|
|
|
|
2020-11-07 02:49:32 +03:00
|
|
|
|
|
|
|
|
|
|
|
|
|
/*********************************************************************/
|
2020-11-07 05:36:20 +03:00
|
|
|
// helpers...
|
2020-11-07 02:49:32 +03:00
|
|
|
|
2020-11-15 05:13:35 +03:00
|
|
|
/* XXX LEGACY...
|
2020-11-07 04:38:08 +03:00
|
|
|
var makeEvent = function(func, mode){
|
2020-11-07 02:49:32 +03:00
|
|
|
return Object.assign(
|
|
|
|
|
func,
|
2020-11-07 04:38:08 +03:00
|
|
|
{__event__: mode || true}) }
|
|
|
|
|
var makeActionEvent = function(func){
|
|
|
|
|
return makeEvent(func, 'action') }
|
2020-11-15 05:13:35 +03:00
|
|
|
//*/
|
2020-11-07 02:49:32 +03:00
|
|
|
|
|
|
|
|
|
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
|
|
|
|
2020-11-13 13:37:10 +03:00
|
|
|
// XXX use ./event...
|
2020-11-07 02:49:32 +03:00
|
|
|
var Queue =
|
|
|
|
|
module.Queue = object.Constructor('Queue', Array, {
|
2020-11-07 05:36:20 +03:00
|
|
|
// create a running queue...
|
2020-11-07 03:19:52 +03:00
|
|
|
run: function(...tasks){
|
|
|
|
|
return this({ state: 'running' }, ...tasks) },
|
2020-11-07 02:49:32 +03:00
|
|
|
|
2020-11-15 03:12:33 +03:00
|
|
|
}, object.mixinFlat({
|
2020-11-07 05:36:20 +03:00
|
|
|
// config...
|
|
|
|
|
//
|
2020-11-07 02:49:32 +03:00
|
|
|
pool_size: 8,
|
2020-11-07 05:36:20 +03:00
|
|
|
|
2020-11-07 02:49:32 +03:00
|
|
|
poling_delay: 200,
|
2020-11-07 05:36:20 +03:00
|
|
|
|
|
|
|
|
auto_stop: false,
|
|
|
|
|
|
2020-11-07 02:49:32 +03:00
|
|
|
|
|
|
|
|
__state: null,
|
|
|
|
|
get state(){
|
|
|
|
|
return this.__state
|
|
|
|
|
|| 'stopped' },
|
|
|
|
|
set state(value){
|
2020-11-07 05:36:20 +03:00
|
|
|
if(value == 'running'){
|
|
|
|
|
this.start()
|
|
|
|
|
} else if(value == 'stopped'){
|
|
|
|
|
this.stop() } },
|
2020-11-07 02:49:32 +03:00
|
|
|
|
|
|
|
|
|
2020-11-07 05:36:20 +03:00
|
|
|
// events/actions - state transitions...
|
|
|
|
|
//
|
2020-11-15 03:12:33 +03:00
|
|
|
start: events.Event('start', function(handle){
|
|
|
|
|
// can't start while running...
|
|
|
|
|
if(this.state == 'running'){
|
2020-11-15 05:13:35 +03:00
|
|
|
return handle(false) }
|
2020-11-15 03:12:33 +03:00
|
|
|
this.__state = 'running'
|
|
|
|
|
this._run() }),
|
|
|
|
|
stop: events.Event('stop', function(handle){
|
|
|
|
|
// can't stop while not running...
|
|
|
|
|
if(this.state == 'stopped'){
|
2020-11-15 05:13:35 +03:00
|
|
|
return handle(false) }
|
|
|
|
|
this.__state = 'stopped' }),
|
2020-11-07 05:36:20 +03:00
|
|
|
|
|
|
|
|
|
|
|
|
|
// events/actions - state transitions...
|
|
|
|
|
//
|
2020-11-15 03:12:33 +03:00
|
|
|
clear: events.Event(function(handler){
|
|
|
|
|
this.splice(0, this.length) }),
|
2020-11-07 05:36:20 +03:00
|
|
|
|
|
|
|
|
|
2020-11-07 02:49:32 +03:00
|
|
|
// events...
|
2020-11-07 05:36:20 +03:00
|
|
|
//
|
2020-11-15 03:12:33 +03:00
|
|
|
taskStarting: events.Event('taskStarting'),
|
|
|
|
|
taskCompleted: events.Event('taskCompleted'),
|
|
|
|
|
queueEmpty: events.Event('queueEmpty'),
|
2020-11-07 02:49:32 +03:00
|
|
|
|
2020-11-09 06:22:32 +03:00
|
|
|
// helpers...
|
|
|
|
|
//
|
|
|
|
|
// XXX how do we reference the tasks here???
|
|
|
|
|
// - indexes
|
|
|
|
|
// - ranges -- simelar to .slice(..)
|
|
|
|
|
// - by value
|
|
|
|
|
// XXX
|
|
|
|
|
prioritize: function(){},
|
|
|
|
|
// XXX same as prioritize but adds stuff to the tail...
|
|
|
|
|
delay: function(){},
|
2020-11-07 05:36:20 +03:00
|
|
|
|
|
|
|
|
// main runner...
|
|
|
|
|
//
|
|
|
|
|
// NOTE: we do not store the exec results...
|
2020-11-07 02:49:32 +03:00
|
|
|
// NOTE: not intended for direct use and will likely have no effect
|
|
|
|
|
// if called directly...
|
|
|
|
|
__running: null,
|
|
|
|
|
_run: function(){
|
|
|
|
|
// if we are not running stop immidiately...
|
|
|
|
|
if(this.state != 'running'){
|
|
|
|
|
return this }
|
|
|
|
|
|
|
|
|
|
var that = this
|
|
|
|
|
var running = this.__running = this.__running || []
|
|
|
|
|
|
|
|
|
|
// handle queue...
|
|
|
|
|
while(this.length > 0
|
|
|
|
|
&& this.state == 'running'
|
|
|
|
|
&& running.length < (this.pool_size || Infinity) ){
|
|
|
|
|
|
|
|
|
|
var task = this.shift()
|
2020-11-15 05:59:19 +03:00
|
|
|
// XXX BUG this executes the task for some reson...
|
2020-11-07 04:06:35 +03:00
|
|
|
this.trigger('taskStarting', task)
|
|
|
|
|
|
|
|
|
|
// run...
|
2020-11-07 02:49:32 +03:00
|
|
|
var res = typeof(task) == 'function' ?
|
|
|
|
|
task()
|
|
|
|
|
: task
|
|
|
|
|
|
|
|
|
|
// pool async (promise) task...
|
|
|
|
|
if(typeof((res || {}).finally) == 'function'
|
|
|
|
|
// one post handler is enough...
|
|
|
|
|
&& !running.includes(res)){
|
|
|
|
|
running.push(res)
|
|
|
|
|
res.finally(function(){
|
|
|
|
|
// remove from running...
|
|
|
|
|
running.splice(0, running.length,
|
|
|
|
|
// NOTE: there can be multiple occurences of res...
|
|
|
|
|
...running
|
|
|
|
|
.filter(function(e){ return e !== res }))
|
|
|
|
|
// finishup...
|
|
|
|
|
that
|
2020-11-15 05:59:19 +03:00
|
|
|
// XXX BUG this executes the task for some reson...
|
2020-11-07 02:49:32 +03:00
|
|
|
.trigger('taskCompleted', task, res)
|
|
|
|
|
._run() })
|
|
|
|
|
|
|
|
|
|
// completed sync task...
|
|
|
|
|
} else {
|
2020-11-15 05:59:19 +03:00
|
|
|
// XXX BUG this executes the task for some reson...
|
2020-11-07 02:49:32 +03:00
|
|
|
this.trigger('taskCompleted', task, res) } }
|
|
|
|
|
|
2020-11-07 03:30:03 +03:00
|
|
|
// empty queue -> pole or stop...
|
2020-11-07 02:49:32 +03:00
|
|
|
//
|
|
|
|
|
// NOTE: we endup here in two cases:
|
|
|
|
|
// - the pool is full
|
|
|
|
|
// - the queue is empty
|
|
|
|
|
// NOTE: we do not care about stopping the timer when changing
|
|
|
|
|
// state as ._run() will stop itself...
|
|
|
|
|
//
|
|
|
|
|
// XXX will this be collected by the GC if it is polling???
|
|
|
|
|
if(this.length == 0
|
2020-11-07 03:30:03 +03:00
|
|
|
&& this.state == 'running'){
|
2020-11-07 04:38:08 +03:00
|
|
|
this.trigger('queueEmpty')
|
|
|
|
|
|
|
|
|
|
// auto-stop...
|
2020-11-07 05:36:20 +03:00
|
|
|
this.auto_stop ?
|
2020-11-07 03:30:03 +03:00
|
|
|
this.stop()
|
|
|
|
|
// pole...
|
|
|
|
|
: (this.poling_delay
|
|
|
|
|
&& setTimeout(
|
|
|
|
|
this._run.bind(this),
|
|
|
|
|
this.poling_delay || 200)) }
|
2020-11-07 02:49:32 +03:00
|
|
|
|
|
|
|
|
return this },
|
|
|
|
|
|
2020-11-07 05:36:20 +03:00
|
|
|
|
|
|
|
|
// constructor argument handling...
|
|
|
|
|
//
|
|
|
|
|
// Queue()
|
|
|
|
|
// -> queue
|
|
|
|
|
//
|
|
|
|
|
// Queue(..,tasks)
|
|
|
|
|
// -> queue
|
|
|
|
|
//
|
|
|
|
|
// Queue(options)
|
|
|
|
|
// Queue(options, ..,tasks)
|
|
|
|
|
// -> queue
|
|
|
|
|
//
|
2020-11-07 02:49:32 +03:00
|
|
|
__init__: function(options){
|
|
|
|
|
if(this[0] instanceof Object
|
|
|
|
|
&& typeof(this[0]) != 'function'
|
|
|
|
|
&& typeof(this[0].finally) != 'function'){
|
|
|
|
|
Object.assign(this, this.shift()) }
|
|
|
|
|
this._run() },
|
2020-11-15 05:13:35 +03:00
|
|
|
},
|
|
|
|
|
// the event API mixin...
|
|
|
|
|
events.EventMixin))
|
2020-11-07 02:49:32 +03:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**********************************************************************
|
|
|
|
|
* vim:set ts=4 sw=4 : */ return module })
|