| 
									
										
										
										
											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-16 02:38:19 +03:00
										 |  |  | require('./Array') | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-15 00:24:22 +03:00
										 |  |  | var events = require('./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
 | 
					
						
							| 
									
										
										
										
											2020-11-16 02:38:19 +03:00
										 |  |  | 	prioritize: function(...tasks){ | 
					
						
							|  |  |  | 		return this.sortAs(tasks) }, | 
					
						
							| 
									
										
										
										
											2020-11-09 06:22:32 +03:00
										 |  |  | 	// XXX same as prioritize but adds stuff to the tail...
 | 
					
						
							| 
									
										
										
										
											2020-11-16 02:38:19 +03:00
										 |  |  | 	delay: function(...tasks){ | 
					
						
							| 
									
										
										
										
											2020-11-16 05:18:55 +03:00
										 |  |  | 		return this.sortAs(tasks, true) }, | 
					
						
							| 
									
										
										
										
											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 }) |