mirror of
https://gitlab.silvrtree.co.uk/martind2000/nci.git
synced 2025-02-04 11:30:14 +00:00
120 lines
2.9 KiB
JavaScript
120 lines
2.9 KiB
JavaScript
'use strict';
|
|
|
|
var _ = require('underscore');
|
|
|
|
|
|
function Node(params) {
|
|
this.type = params.type;
|
|
this.maxExecutorsCount = params.maxExecutorsCount;
|
|
this.name = params.name;
|
|
this.usageStrategy = params.usageStrategy || 'maximum';
|
|
|
|
if (!this.usageStrategiesHash[this.usageStrategy]) {
|
|
throw new Error('Unknown usage strategy: ' + this.usageStrategy);
|
|
}
|
|
|
|
this.executors = {};
|
|
}
|
|
|
|
exports.Node = Node;
|
|
|
|
Node.prototype.usageStrategiesHash = {maximum: 1, specificProject: 1};
|
|
|
|
Node.prototype._getBlockerExecutor = function(getBlockers, getTarget) {
|
|
return _(this.executors).find(function(executor) {
|
|
var target = getTarget(executor);
|
|
return _(getBlockers(executor)).find(function(blocker) {
|
|
if (_(blocker).isRegExp()) {
|
|
return blocker.test(target);
|
|
} else {
|
|
return blocker === target;
|
|
}
|
|
});
|
|
})
|
|
};
|
|
|
|
Node.prototype.getExecutorWaitReason = function(project) {
|
|
var waitReason;
|
|
|
|
var targetNodeNames = project.node && project.node.target;
|
|
|
|
if (targetNodeNames && !_(targetNodeNames).isArray()) {
|
|
targetNodeNames = [targetNodeNames];
|
|
}
|
|
|
|
if (targetNodeNames && !_(targetNodeNames).contains(this.name)) {
|
|
waitReason = this.name + ': not a target node';
|
|
} else if (this.usageStrategy === 'specificProject' && !targetNodeNames) {
|
|
waitReason = this.name + ': only for specific projects';
|
|
} else if (_(this.executors).size() >= this.maxExecutorsCount) {
|
|
waitReason = this.name + ': all executors are busy';
|
|
} else if (project.name in this.executors) {
|
|
waitReason = this.name + ': project already running on node';
|
|
} else {
|
|
var blockerExecutor;
|
|
|
|
if (project.blockedBy) {
|
|
blockerExecutor = this._getBlockerExecutor(
|
|
function(executor) {
|
|
return project.blockedBy;
|
|
},
|
|
function(executor) {
|
|
return executor.project.name;
|
|
}
|
|
);
|
|
}
|
|
|
|
if (!blockerExecutor) {
|
|
blockerExecutor = this._getBlockerExecutor(
|
|
function(executor) {
|
|
return executor.project.blocks;
|
|
},
|
|
function(executor) {
|
|
return project.name;
|
|
}
|
|
);
|
|
}
|
|
|
|
if (blockerExecutor) {
|
|
waitReason = (
|
|
this.name + ': blocked by currently running "' +
|
|
blockerExecutor.project.name + '"'
|
|
);
|
|
}
|
|
}
|
|
|
|
return waitReason;
|
|
};
|
|
|
|
Node.prototype.hasFreeExecutor = function(project) {
|
|
return !this.getExecutorWaitReason(project);
|
|
};
|
|
|
|
Node.prototype.getFreeExecutorsCount = function() {
|
|
return this.maxExecutorsCount - _(this.executors).size();
|
|
};
|
|
|
|
Node.prototype.hasScmChanges = function(project, callback) {
|
|
this._createExecutor(project).hasScmChanges(callback);
|
|
};
|
|
|
|
Node.prototype.run = function(project, params, callback) {
|
|
var self = this;
|
|
|
|
var waitReason = this.getExecutorWaitReason(project);
|
|
if (waitReason) {
|
|
throw new Error(
|
|
'Project "' + project.name + '" should wait because: ' + waitReason
|
|
);
|
|
}
|
|
|
|
this.executors[project.name] = this._createExecutor(project);
|
|
|
|
this.executors[project.name].run(params, function(err) {
|
|
delete self.executors[project.name];
|
|
callback(err);
|
|
});
|
|
|
|
return this.executors[project.name];
|
|
};
|