CartoDB-SQL-API/batch/scheduler/host-scheduler.js
Raul Ochoa 3a57331a54 Delegate job scheduling
There is a host scheduler managing the host locking.

When it can acquire a lock over the host it will delegate
all the tasks related to that host to the same scheduler.

This scheduler will take care of how many jobs it will submit,
and in which order. It's also responsible for guaranteeing the
execution order per user.

Capacity planner dictates how many jobs can be run at the
same time in a given host. There are two simple strategies:

1. Infinity: it will attempt to run as many jobs as different users.
2. One: it will run just one job at the same time.

Missing things:
 - Handle lock renewal failures.
 - Fair scheduling for pending/waiting users.
 - Capacity based on real resources.
2016-10-18 20:43:15 +02:00

60 lines
1.8 KiB
JavaScript

'use strict';
var debug = require('../util/debug')('host-scheduler');
var Scheduler = require('./scheduler');
var Locker = require('../leader/locker');
var InfinityCapacity = require('./capacity/infinity');
//var OneCapacity = require('./capacity/one');
function HostScheduler(taskRunner, redisPool) {
this.taskRunner = taskRunner;
this.locker = Locker.create('redis-distlock', { pool: redisPool });
this.locker.on('error', function(err, host) {
debug('Locker.error %s', err.message);
this.unlock(host);
}.bind(this));
// host => Scheduler
this.schedulers = {};
}
module.exports = HostScheduler;
HostScheduler.prototype.schedule = function(host, user, callback) {
this.lock(host, function(err, scheduler) {
if (err) {
return callback(err);
}
var wasRunning = scheduler.add(user);
return callback(err, wasRunning);
});
};
HostScheduler.prototype.lock = function(host, callback) {
debug('lock(%s)', host);
var self = this;
this.locker.lock(host, function(err) {
if (err) {
debug('Could not lock host=%s. Reason: %s', host, err.message);
return callback(err);
}
if (!self.schedulers.hasOwnProperty(host)) {
var scheduler = new Scheduler(new InfinityCapacity(host), self.taskRunner);
scheduler.on('done', self.unlock.bind(self, host));
self.schedulers[host] = scheduler;
}
debug('Locked host=%s', host);
return callback(null, self.schedulers[host]);
});
};
HostScheduler.prototype.unlock = function(host) {
debug('unlock(%s)', host);
if (this.schedulers.hasOwnProperty(host)) {
// TODO stop scheduler?
delete this.schedulers[host];
}
this.locker.unlock(host, debug);
};