'use strict'
const util = require('util')
const Worker = require('./Worker.js')
const Promise = require('bluebird')
const debug = require('debug')('relieve:seriesworker')
/**
* A Queue Worker that process ending tasks in concurrency
* @module workers/QueueWorker
*/
/**
* @class
* @extends module:workers/Worker~Worker
* @property {Number} [concurrency=1] The concurrency value
*/
function QueueWorker(options) {
if(!(this instanceof QueueWorker)) { return new QueueWorker(options) }
if(!options)
options = {}
Worker.call(this, options)
if(!options.concurrency)
options.concurrency = 1
this.options = options
}
util.inherits(QueueWorker, Worker)
/**
* @throws {TypeError} if task has no start method
*/
QueueWorker.prototype.add = function(task) {
if(!task.start)
throw new TypeError('Task must be an instance of ScriptTask or CallableTask')
Worker.prototype.add.call(this, task)
return this
}
Object.defineProperty(QueueWorker.prototype, 'concurrency', {
get: function getConcurrency() {
return this.options.concurrency
},
set: function setConcurrency(val) {
this.options.concurrency = val
}
})
/**
* Runs tasks in the stack
* Tasks must exit to fullfil the promise, they run in concurrency
* @see options.concurrency
* @param Task ...tasks if none provided the whole stack will run
* @return Promise resolves when every task exited
*/
QueueWorker.prototype.run = function(...args) {
let stack = []
if(args.length === 0)
stack = this.tasks.values()
else {
for(let i in args) {
stack.push(this.tasks.get(args[i]))
}
}
return Promise.all(stack).map(function(e) {
return e.start()
.then(() => {
return new Promise((resolve, reject) => {
debug('start task %s', e.name);
e.once('exit', function(code) {
debug('exit task %s', e.name);
resolve(code)
})
})
})
}, {
concurrency: this.options.concurrency
})
}
module.exports = QueueWorker