2016-10-19 18:39:33 +08:00
|
|
|
'use strict';
|
|
|
|
|
|
|
|
require('../../helper');
|
2019-10-04 00:24:39 +08:00
|
|
|
var debug = require('../../../lib/batch/util/debug')('scheduler-test');
|
2016-10-19 18:39:33 +08:00
|
|
|
var assert = require('../../support/assert');
|
2019-10-04 00:24:39 +08:00
|
|
|
var Scheduler = require('../../../lib/batch/scheduler/scheduler');
|
|
|
|
var FixedCapacity = require('../../../lib/batch/scheduler/capacity/fixed');
|
2016-10-19 18:39:33 +08:00
|
|
|
|
2019-12-24 01:19:08 +08:00
|
|
|
describe('scheduler', function () {
|
2016-10-21 17:42:27 +08:00
|
|
|
var USER_FINISHED = true;
|
|
|
|
|
2016-10-21 17:10:17 +08:00
|
|
|
var USER_A = 'userA';
|
|
|
|
var USER_B = 'userB';
|
|
|
|
var USER_C = 'userC';
|
|
|
|
|
2019-12-24 01:19:08 +08:00
|
|
|
function TaskRunner (userTasks) {
|
2016-10-19 18:39:33 +08:00
|
|
|
this.results = [];
|
|
|
|
this.userTasks = userTasks;
|
|
|
|
}
|
|
|
|
|
2019-12-24 01:19:08 +08:00
|
|
|
TaskRunner.prototype.run = function (user, callback) {
|
2016-10-19 18:39:33 +08:00
|
|
|
this.results.push(user);
|
|
|
|
this.userTasks[user]--;
|
2019-12-24 01:19:08 +08:00
|
|
|
setTimeout(function () {
|
2016-10-21 02:16:57 +08:00
|
|
|
return callback(null, this.userTasks[user] === 0);
|
|
|
|
}.bind(this), 50);
|
2016-10-19 18:39:33 +08:00
|
|
|
};
|
|
|
|
|
2019-12-24 01:19:08 +08:00
|
|
|
function ManualTaskRunner () {
|
2016-10-21 17:42:27 +08:00
|
|
|
this.userTasks = {};
|
|
|
|
}
|
|
|
|
|
2019-12-24 01:19:08 +08:00
|
|
|
ManualTaskRunner.prototype.run = function (user, callback) {
|
2019-12-26 23:10:41 +08:00
|
|
|
if (!Object.prototype.hasOwnProperty.call(this.userTasks, user)) {
|
2016-10-21 17:42:27 +08:00
|
|
|
this.userTasks[user] = [];
|
|
|
|
}
|
|
|
|
this.userTasks[user].push(callback);
|
|
|
|
};
|
|
|
|
|
2019-12-24 01:19:08 +08:00
|
|
|
ManualTaskRunner.prototype.dispatch = function (user, isDone) {
|
2019-12-26 23:10:41 +08:00
|
|
|
if (Object.prototype.hasOwnProperty.call(this.userTasks, user)) {
|
2016-10-21 17:42:27 +08:00
|
|
|
var cb = this.userTasks[user].shift();
|
|
|
|
if (cb) {
|
|
|
|
return cb(null, isDone);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2016-10-19 18:39:33 +08:00
|
|
|
// simulate one by one or infinity capacity
|
2016-10-21 05:47:39 +08:00
|
|
|
var capacities = [new FixedCapacity(1), new FixedCapacity(2), new FixedCapacity(Infinity)];
|
2016-10-19 18:39:33 +08:00
|
|
|
|
2019-12-24 01:19:08 +08:00
|
|
|
capacities.forEach(function (capacity) {
|
2016-10-21 05:47:39 +08:00
|
|
|
it('regression #1', function (done) {
|
2016-10-21 02:16:57 +08:00
|
|
|
var taskRunner = new TaskRunner({
|
|
|
|
userA: 2,
|
|
|
|
userB: 2
|
|
|
|
});
|
|
|
|
var scheduler = new Scheduler(capacity, taskRunner);
|
2016-10-21 17:10:17 +08:00
|
|
|
scheduler.add(USER_A);
|
|
|
|
scheduler.add(USER_B);
|
2016-10-21 02:16:57 +08:00
|
|
|
|
2019-12-24 01:19:08 +08:00
|
|
|
scheduler.on('done', function () {
|
2016-10-21 02:16:57 +08:00
|
|
|
var results = taskRunner.results;
|
|
|
|
|
2019-12-26 21:01:18 +08:00
|
|
|
assert.strictEqual(results.length, 4);
|
2016-10-21 02:16:57 +08:00
|
|
|
|
2019-12-26 21:01:18 +08:00
|
|
|
assert.strictEqual(results[0], USER_A);
|
|
|
|
assert.strictEqual(results[1], USER_B);
|
|
|
|
assert.strictEqual(results[2], USER_A);
|
|
|
|
assert.strictEqual(results[3], USER_B);
|
2016-10-21 02:16:57 +08:00
|
|
|
|
|
|
|
return done();
|
|
|
|
});
|
|
|
|
|
|
|
|
scheduler.schedule();
|
|
|
|
});
|
|
|
|
|
2016-10-21 17:42:27 +08:00
|
|
|
it('regression #2: it should restart task after it was done but got re-scheduled', function (done) {
|
|
|
|
var taskRunner = new ManualTaskRunner();
|
2016-10-21 05:47:39 +08:00
|
|
|
var scheduler = new Scheduler(capacity, taskRunner);
|
2016-10-21 17:42:27 +08:00
|
|
|
debug('Adding users A and B');
|
2016-10-21 17:10:17 +08:00
|
|
|
scheduler.add(USER_A);
|
|
|
|
scheduler.add(USER_B);
|
2016-10-21 05:47:39 +08:00
|
|
|
|
2016-10-21 17:42:27 +08:00
|
|
|
var acquiredUsers = [];
|
2016-10-21 05:47:39 +08:00
|
|
|
|
2019-12-24 01:19:08 +08:00
|
|
|
scheduler.on('done', function () {
|
2016-10-21 17:42:27 +08:00
|
|
|
debug('Users %j', acquiredUsers);
|
2019-12-26 21:01:18 +08:00
|
|
|
assert.strictEqual(acquiredUsers[0], USER_A);
|
|
|
|
assert.strictEqual(acquiredUsers[1], USER_B);
|
|
|
|
assert.strictEqual(acquiredUsers[2], USER_A);
|
|
|
|
assert.strictEqual(acquiredUsers[3], USER_B);
|
2016-10-21 05:47:39 +08:00
|
|
|
|
2019-12-26 21:01:18 +08:00
|
|
|
assert.strictEqual(acquiredUsers.length, 4);
|
2016-10-21 05:47:39 +08:00
|
|
|
|
|
|
|
return done();
|
|
|
|
});
|
|
|
|
|
2019-12-24 01:19:08 +08:00
|
|
|
scheduler.on('acquired', function (user) {
|
2016-10-21 17:42:27 +08:00
|
|
|
debug('Acquired user %s', user);
|
|
|
|
acquiredUsers.push(user);
|
|
|
|
});
|
2016-10-21 05:47:39 +08:00
|
|
|
|
|
|
|
scheduler.schedule();
|
2016-10-21 17:42:27 +08:00
|
|
|
|
|
|
|
debug('User A will be mark as DONE');
|
|
|
|
taskRunner.dispatch(USER_A, USER_FINISHED);
|
|
|
|
|
|
|
|
debug('User B should be running');
|
|
|
|
debug('User A submit a new task');
|
|
|
|
scheduler.add(USER_A);
|
|
|
|
|
|
|
|
debug('User B will get another task to run');
|
|
|
|
taskRunner.dispatch(USER_B);
|
|
|
|
|
|
|
|
debug('User A should start working on this new task');
|
|
|
|
taskRunner.dispatch(USER_A, USER_FINISHED);
|
|
|
|
taskRunner.dispatch(USER_B, USER_FINISHED);
|
2016-10-21 05:47:39 +08:00
|
|
|
});
|
|
|
|
|
2016-10-19 18:39:33 +08:00
|
|
|
it('should run tasks', function (done) {
|
|
|
|
var taskRunner = new TaskRunner({
|
|
|
|
userA: 1
|
|
|
|
});
|
|
|
|
var scheduler = new Scheduler(capacity, taskRunner);
|
2016-10-21 17:10:17 +08:00
|
|
|
scheduler.add(USER_A);
|
2016-10-19 18:39:33 +08:00
|
|
|
|
2019-12-24 01:19:08 +08:00
|
|
|
scheduler.on('done', function () {
|
2016-10-19 18:39:33 +08:00
|
|
|
var results = taskRunner.results;
|
|
|
|
|
2019-12-26 21:01:18 +08:00
|
|
|
assert.strictEqual(results.length, 1);
|
2016-10-19 18:39:33 +08:00
|
|
|
|
2019-12-26 21:01:18 +08:00
|
|
|
assert.strictEqual(results[0], USER_A);
|
2016-10-19 18:39:33 +08:00
|
|
|
|
|
|
|
return done();
|
|
|
|
});
|
|
|
|
|
|
|
|
scheduler.schedule();
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should run tasks for different users', function (done) {
|
|
|
|
var taskRunner = new TaskRunner({
|
|
|
|
userA: 1,
|
|
|
|
userB: 1,
|
|
|
|
userC: 1
|
|
|
|
});
|
|
|
|
var scheduler = new Scheduler(capacity, taskRunner);
|
2016-10-21 17:10:17 +08:00
|
|
|
scheduler.add(USER_A);
|
|
|
|
scheduler.add(USER_B);
|
|
|
|
scheduler.add(USER_C);
|
2016-10-19 18:39:33 +08:00
|
|
|
|
2019-12-24 01:19:08 +08:00
|
|
|
scheduler.on('done', function () {
|
2016-10-19 18:39:33 +08:00
|
|
|
var results = taskRunner.results;
|
|
|
|
|
2019-12-26 21:01:18 +08:00
|
|
|
assert.strictEqual(results.length, 3);
|
2016-10-19 18:39:33 +08:00
|
|
|
|
2019-12-26 21:01:18 +08:00
|
|
|
assert.strictEqual(results[0], USER_A);
|
|
|
|
assert.strictEqual(results[1], USER_B);
|
|
|
|
assert.strictEqual(results[2], USER_C);
|
2016-10-19 18:39:33 +08:00
|
|
|
|
|
|
|
return done();
|
|
|
|
});
|
|
|
|
|
|
|
|
scheduler.schedule();
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should be fair when scheduling tasks', function (done) {
|
|
|
|
var taskRunner = new TaskRunner({
|
|
|
|
userA: 3,
|
|
|
|
userB: 2,
|
|
|
|
userC: 1
|
|
|
|
});
|
|
|
|
|
|
|
|
var scheduler = new Scheduler(capacity, taskRunner);
|
2016-10-21 17:10:17 +08:00
|
|
|
scheduler.add(USER_A);
|
|
|
|
scheduler.add(USER_A);
|
|
|
|
scheduler.add(USER_A);
|
|
|
|
scheduler.add(USER_B);
|
|
|
|
scheduler.add(USER_B);
|
|
|
|
scheduler.add(USER_C);
|
2016-10-19 18:39:33 +08:00
|
|
|
|
2019-12-24 01:19:08 +08:00
|
|
|
scheduler.on('done', function () {
|
2016-10-19 18:39:33 +08:00
|
|
|
var results = taskRunner.results;
|
|
|
|
|
2019-12-26 21:01:18 +08:00
|
|
|
assert.strictEqual(results.length, 6);
|
2016-10-19 18:39:33 +08:00
|
|
|
|
2019-12-26 21:01:18 +08:00
|
|
|
assert.strictEqual(results[0], USER_A);
|
|
|
|
assert.strictEqual(results[1], USER_B);
|
|
|
|
assert.strictEqual(results[2], USER_C);
|
|
|
|
assert.strictEqual(results[3], USER_A);
|
|
|
|
assert.strictEqual(results[4], USER_B);
|
|
|
|
assert.strictEqual(results[5], USER_A);
|
2016-10-19 18:39:33 +08:00
|
|
|
|
|
|
|
return done();
|
|
|
|
});
|
|
|
|
|
|
|
|
scheduler.schedule();
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|