add distributor with minimal testing

This commit is contained in:
oleg 2015-04-09 21:55:29 +03:00
parent 0650023ba3
commit 7b8c67e941
2 changed files with 153 additions and 0 deletions

83
lib/distributor.js Normal file
View File

@ -0,0 +1,83 @@
'use strict';
var Steppy = require('twostep').Steppy,
_ = require('underscore'),
Node = require('./node').Node;
function Distributor(params) {
var self = this;
// nodes to execute builds
self.nodes = _(params.nodes).map(function(nodeParams) {
return self._createNode(nodeParams);
});
// queued projects to build
self.queue = [];
}
exports.Distributor = Distributor;
Distributor.prototype._createNode = function(nodeParams) {
return new Node(nodeParams);
};
Distributor.prototype._runNext = function(callback) {
var self = this;
Steppy(
function() {
var node;
var queueItemIndex = _(self.queue).findIndex(function(item) {
node = _(self.nodes).find(function(node) {
return node.hasFreeExecutor(item.project);
});
return node;
});
// quit if we have no suitable project
if (queueItemIndex) {
return callback();
}
this.pass(node);
var queueItem = self.queue[queueItemIndex];
this.pass(queueItemIndex, queueItem);
queueItem.build.status = 'in-progress';
self._updateBuild(queueItem.build, this.slot());
},
function(err, node, queueItemIndex, queueItem, build) {
self.queue.splice(queueItemIndex, 1);
var stepCallback = this.slot();
node.run(queueItem.project, build.params, function(err) {
build.status = err ? 'error' : 'done';
self._updateBuild(build, stepCallback);
});
},
callback
);
};
Distributor.prototype._updateBuild = function(build, callback) {
callback(null, build);
};
Distributor.prototype.run = function(project, params, callback) {
var self = this;
Steppy(
function() {
self._updateBuild({
project: project,
params: params,
status: 'waiting'
}, this.slot());
},
function(err, build) {
self.queue.push({project: project, build: build});
self._runNext(this.slot());
},
callback
);
};

70
test/distributor.js Normal file
View File

@ -0,0 +1,70 @@
'use strict';
var Distributor = require('../lib/distributor').Distributor,
Node = require('../lib/node').Node,
expect = require('expect.js');
describe('Distributor', function() {
var distributor,
project1 = {name: 'project1'};
describe('with sucess project', function() {
var originalCreateNode,
originalUpdateBuild;
before(function() {
originalCreateNode = Distributor.prototype._createNode;
Distributor.prototype._createNode = function(params) {
var node = new Node(params);
node._createExecutor = function() {
return {run: function(params, callback) {
setTimeout(callback, 100);
}};
};
return node;
};
originalUpdateBuild = Distributor.prototype._updateBuild;
var updateBuildNumber = 1;
Distributor.prototype._updateBuild = function(build, callback) {
if (updateBuildNumber === 1) {
expect(distributor.queue).length(0);
expect(build.status).equal('waiting');
} else if (updateBuildNumber === 2) {
expect(distributor.queue).length(1);
expect(build.status).equal('in-progress');
} else if (updateBuildNumber === 3) {
expect(distributor.queue).length(0);
expect(build.status).equal('done');
} else {
throw new Error('Should never happend');
}
updateBuildNumber++;
callback(null, build)
};
});
it('instance should be created without errors', function() {
distributor = new Distributor({
nodes: [{type: 'local', maxExecutorsCount: 1}]
});
});
it('should run without errors', function() {
distributor.run(project1, {}, function(err) {
expect(err).not.ok();
});
});
it('wait for project done (should no errors)', function(done) {
setTimeout(done, 100);
});
after(function() {
Distributor.prototype._createNode = originalCreateNode;
Distributor.prototype._updateBuild = originalUpdateBuild;
});
});
});