add and show build wait reason

This commit is contained in:
oleg 2015-06-15 02:27:58 +03:00
parent b23edf202f
commit 361a5a5436
4 changed files with 65 additions and 16 deletions

View File

@ -37,6 +37,9 @@ Distributor.prototype._runNext = function(callback) {
Steppy(
function() {
// update wait reasons for all queue items before run
self._updateWaitReasons();
var node;
var queueItemIndex = _(self.queue).findIndex(function(item) {
node = _(self.nodes).find(function(node) {
@ -88,11 +91,28 @@ Distributor.prototype._runNext = function(callback) {
executor.once('scmData', function(scmData) {
self._updateBuild(build, {scm: scmData});
});
// update wait reasons for all queue items after run
self._updateWaitReasons();
},
callback
);
};
Distributor.prototype._updateWaitReasons = function() {
var self = this;
_(self.queue).each(function(item) {
var waitReasons = _(self.nodes).map(function(node) {
return node.getExecutorWaitReason(item.project);
});
var waitReason = _(waitReasons).compact().join(', ');
if (waitReason !== item.build.waitReason) {
self._updateBuild(item.build, {waitReason: waitReason});
}
});
};
Distributor.prototype._onBuildComplete = function(err, build, callback) {
var self = this;

View File

@ -12,14 +12,22 @@ function Node(params) {
exports.Node = Node;
Node.prototype.hasFreeExecutor = function(project) {
return (
// can't build same project twice at the same time on same node
project.name in this.executors === false &&
_(this.executors).size() < this.maxExecutorsCount
);
Node.prototype.getExecutorWaitReason = function(project) {
var waitReason;
if (_(this.executors).size() >= this.maxExecutorsCount) {
waitReason = 'All executors are busy';
} else if (project.name in this.executors) {
waitReason = 'Project already running on node';
}
return waitReason;
};
Node.prototype.hasFreeExecutor = function(project) {
return !this.getExecutorWaitReason(project);
};
Node.prototype._createExecutor = function(project) {
return createExecutor({
type: this.type,
@ -29,8 +37,12 @@ Node.prototype._createExecutor = function(project) {
Node.prototype.run = function(project, params, callback) {
var self = this;
if (!this.hasFreeExecutor(project)) {
throw new Error('No free executors for project: ' + project.name);
var waitReason = this.getExecutorWaitReason(project);
if (waitReason) {
throw new Error(
'Project "' + project.name + '" should wait because: ' + waitReason
);
}
this.executors[project.name] = this._createExecutor(project);

View File

@ -30,6 +30,11 @@ mixin statusText(build)
span #
span= build.number
if build.waitReason
span (
span= build.waitReason
span , waiting)
if build.status === 'in-progress' && build.currentStep
span (
span= build.currentStep

View File

@ -69,14 +69,20 @@ describe('Distributor', function() {
expect(changes.completed).equal(false);
});
it('build should be in-progress', function() {
it('build should have empty wait reason', function() {
var changes = updateBuildSpy.getCall(1).args[1];
expect(changes).only.have.keys('waitReason');
expect(changes.waitReason).equal('');
});
it('build should be in-progress', function() {
var changes = updateBuildSpy.getCall(2).args[1];
expect(changes).only.have.keys('startDate', 'status');
expect(changes.status).equal('in-progress');
});
it('build should be done', function() {
var changes = updateBuildSpy.getCall(2).args[1];
var changes = updateBuildSpy.getCall(3).args[1];
expect(changes).only.have.keys(
'endDate', 'status', 'completed', 'error'
);
@ -85,8 +91,8 @@ describe('Distributor', function() {
expect(changes.error).equal(null);
});
it('update build called 3 times in total', function() {
expect(updateBuildSpy.callCount).equal(3);
it('update build called 4 times in total', function() {
expect(updateBuildSpy.callCount).equal(4);
});
after(function() {
@ -128,20 +134,26 @@ describe('Distributor', function() {
expect(changes.status).equal('queued');
});
it('build should be in-progress', function() {
it('build should have empty wait reason', function() {
var changes = updateBuildSpy.getCall(1).args[1];
expect(changes).only.have.keys('waitReason');
expect(changes.waitReason).equal('');
});
it('build should be in-progress', function() {
var changes = updateBuildSpy.getCall(2).args[1];
expect(changes.status).equal('in-progress');
});
it('build should be fail', function() {
var changes = updateBuildSpy.getCall(2).args[1];
var changes = updateBuildSpy.getCall(3).args[1];
expect(changes.status).equal('error');
expect(changes.completed).equal(true);
expect(changes.error).equal('Some error');
});
it('update build called 3 times in total', function() {
expect(updateBuildSpy.callCount).equal(3);
it('update build called 4 times in total', function() {
expect(updateBuildSpy.callCount).equal(4);
});
after(function() {