job-manager.js | |
---|---|
/*
* JobManager.js: Creates and manages jobs, workers and job results.
*
* (C) 2010 Charlie Robbins
* MIT LICENSE
*
*/
var util = require('util'),
events = require('events'),
neuron = require('neuron'); | |
function JobManager (options)@options {Object} Settings to use for this instanceConstructor function for the JobManager object which manages a set of workers for a single instance of neuron.Job. | var JobManager = exports.JobManager = function (options) {
options = options || {};
if (options.job && !(options.job instanceof neuron.Job)) {
throw new Error('job must be an instance of neuron.Job');
}
this.concurrency = options.concurrency || 50;
this.job = options.job || {};
this.running = {};
this.waiting = {};
this.queue = [];
}; |
Inherit from events.EventEmitter | util.inherits(JobManager, events.EventEmitter); |
funtion JobManager.prototype.setJob (job)@job {Job} The job to use for this instance.Sets the job for this instance to manage. | JobManager.prototype.setJob = function (job) {
if (this.queue.length > 0) throw new Error('Cannot setJob() with unfinished jobs in queue.');
else if (!(job instanceof neuron.Job)) throw new Error('job must be an instance of neuron.Job');
this.job = job;
}; |
function start (/* variable arguments */)@arguments {variable} The arguments to pass to the running job.Creates a new instance of the Job managed by this instance
by creating a new worker to run which takes | JobManager.prototype.start = function () {
if (!(this.job instanceof neuron.Job)) throw new Error('Cannot runNext() with no job to perform.');
|
Create a unique id for this worker. | workerId = neuron.randomString(32);
while (this.running[workerId] || this.waiting[workerId]) {
workerId = neuron.randomString(32);
}
var self = this,
worker = new neuron.Worker(workerId, this.job, Array.prototype.slice.call(arguments));
worker.once('finish', function () {
self._workComplete(worker);
});
if (Object.keys(this.running).length >= this.concurrency) {
this.waiting[workerId] = worker;
this.queue.push(workerId);
}
else {
this.running[workerId] = worker;
process.nextTick(function () {
worker.run();
});
}
return workerId;
}; |
function JobManager.prototype.getWorker (workerId)@workerId {string} The id of the worker to retreive.Gets a worker with the specified id | JobManager.prototype.getWorker = function (workerId) {
if (this.running[workerId]) {
return this.running[workerId];
}
else if (this.waiting[workerId]) {
return this.waiting[workerId];
}
return null;
}; |
function _workComplete (worker)@worker {Worker} The worker who has just completed.Updates bookkeeping associated with this instance knowing that the given worker is now complete. | JobManager.prototype._workComplete = function (worker) {
var self = this, nextWorker, nextId;
|
Wait a moment before indicating to the user that we are done | process.nextTick(function () {
self.emit('finish', worker);
|
If the queue is now empty, notify the user | if (self.queue.length === 0) {
self.emit('empty');
}
});
delete this.running[worker.id];
this._replenish();
}; |
function _replenish ()Replenishes the running worker by dequeuing waiting workers from | JobManager.prototype._replenish = function () {
var self = this, running = Object.keys(this.running).length,
workerId, started = [];
if (this.queue.length === 0) return false;
else if (running > this.concurrency) return false;
while (running < this.concurrency && (workerId = this.queue.shift())) { |
Close over the workerId and the worker annoymously so we can
user | (function (id, w) {
started.push(id); |
Move the worker from the set of waiting workers to the set of running workers | delete self.waiting[id];
self.running[id] = w;
|
Increment the length of the running workers manually
so we don't have to call | running += 1; |
Start the worker on the next tick. | process.nextTick(function () {
w.run();
});
})(workerId, this.waiting[workerId]);
}
return started;
};
|