webgme-executor-worker
Version:
Worker for connecting to webgme executor framework
243 lines (219 loc) • 8.29 kB
JavaScript
/*globals define*/
/*jshint node:true*/
/**
* @module Executor:NodeWorker
* @author lattmann / https://github.com/lattmann
* @author ksmyth / https://github.com/ksmyth
*/
var nodeRequire = require,
log = function () {
'use strict';
var args = Array.prototype.slice.call(arguments);
args.splice(0, 0, new Date().toISOString());
console.log.apply(console, args);
},
err = function () {
'use strict';
var args = Array.prototype.slice.call(arguments);
args.splice(0, 0, new Date().toISOString());
console.error.apply(console, args);
},
logger = {
debug: log,
log: log,
info: log,
warn: log,
error: err
};
if (typeof define !== 'undefined') {
define('node_worker', [
'blob/BlobClient',
'executor-worker/ExecutorWorker',
'executor/JobInfo',
'executor-worker/ExecutorWorkerController',
'url'
], function (BlobClient, ExecutorWorker, JobInfo, ExecutorWorkerController, url) {
'use strict';
return function (webGMEUrl, tempPath, parameters, availableProcessesContainer) {
var worker,
webGMEPort = url.parse(webGMEUrl).port || (url.parse(webGMEUrl).protocol === 'https:' ? 443 : 80);
worker = new ExecutorWorker({
server: url.parse(webGMEUrl).hostname,
serverPort: webGMEPort,
httpsecure: url.parse(webGMEUrl).protocol === 'https:',
webgmeToken: undefined,
availableProcessesContainer: availableProcessesContainer,
workingDirectory: tempPath,
executorNonce: parameters.executorNonce,
logger: logger,
apiToken: parameters.apiToken
});
log('Connecting to ' + webGMEUrl);
var callback;
worker.queryWorkerAPI(function (err, response) {
if (!err) {
log('Connected to ' + webGMEUrl);
}
var refreshPeriod = 60 * 1000,
disconnected = false;
callback = callback || function (err, response) {
if (err) {
log('Error connecting to ' + webGMEUrl + ' ' + err);
disconnected = true;
} else if (disconnected) {
log('Reconnected to ' + webGMEUrl);
disconnected = false;
}
if (response && response.refreshPeriod) {
refreshPeriod = response.refreshPeriod;
}
/*var timeoutID = */
setTimeout(function () {
worker.queryWorkerAPI(callback);
}, refreshPeriod);
};
callback(err, response);
});
var cancel = function () {
callback = function () {
};
};
return cancel;
};
});
}
function main() {
var fs = nodeRequire('fs'),
path = nodeRequire('path'),
superagent = nodeRequire('superagent'),
configFileName = 'config.json',
workingDirectory = 'executor-temp',
cas;
//https = nodeRequire('https'); FIXME take into use or remove it
if (process.env.LATEST_CERTS) {
cas = nodeRequire('ssl-root-cas/latest');
} else {
cas = nodeRequire('ssl-root-cas');
}
// This is used for tests
if (process.argv.length > 2) {
configFileName = process.argv[2];
if (process.argv.length > 3) {
workingDirectory = process.argv[3];
}
}
cas.inject();
fs.readdirSync(__dirname).forEach(function (file) {
'use strict';
var filename = path.resolve(__dirname, file);
if ((filename.indexOf('.pem') === filename.length - 4) || (filename.indexOf('.crt') === filename.length - 4)) {
log('Adding ' + file + ' to trusted CAs');
cas.addFile(filename);
}
});
superagent.Request.prototype._ca = (require('https').globalAgent.options.ca);
var requirejs = require('./node_worker.classes.build.js').requirejs;
[
'superagent',
'fs',
'util',
'events',
'path',
'child_process',
'minimatch',
'rimraf',
'url',
'q'
].forEach(function (name) {
'use strict';
requirejs.s.contexts._.defined[name] = nodeRequire(name);
});
global.WebGMEGlobal = {
getConfig: function () {
'use strict';
return {};
}
}; // server: config.server, serverPort: config.port, httpsecure: config.protocol==='https' }; } };
var webGMEUrls = Object.create(null),
maxConcurrentJobs = 1,
availableProcessesContainer = { //FIXME check why the definition cannot be moved to global namespace
availableProcesses: maxConcurrentJobs
}; // shared among all ExecutorWorkers
requirejs(['node_worker'], function (addWebGMEConnection) {
'use strict';
var fs = nodeRequire('fs'),
path = nodeRequire('path');
function readConfig() {
var config = {
'http://127.0.0.1:8888': {}
};
try {
var configJSON = fs.readFileSync(configFileName, {
encoding: 'utf8'
});
config = JSON.parse(configJSON);
if (Array.isArray(config)) {
var oldConfig = config;
config = {};
oldConfig.forEach(function (webGMEUrl) {
config[webGMEUrl] = {};
});
} else if (typeof (config) === 'string') {
config = {
config: {}
};
} else {
}
} catch (e) {
if (e.code !== 'ENOENT') {
throw e;
}
}
Object.getOwnPropertyNames(config).forEach(function (key) {
var webGMEUrl;
if (key.indexOf('http') === 0) {
webGMEUrl = key;
if (Object.prototype.hasOwnProperty.call(webGMEUrls, webGMEUrl)) {
} else {
webGMEUrls[webGMEUrl] = addWebGMEConnection(webGMEUrl,
path.join(workingDirectory, '' + workingDirectoryCount++),
config[webGMEUrl], availableProcessesContainer);
}
} else if (key === 'maxConcurrentJobs') {
availableProcessesContainer.availableProcesses += config.maxConcurrentJobs - maxConcurrentJobs;
maxConcurrentJobs = config.maxConcurrentJobs;
} else {
log('Unknown configuration key ' + key);
}
});
// remove webGMEUrls no longer in config
Object.getOwnPropertyNames(webGMEUrls).forEach(function (webGMEUrl) {
if (Object.prototype.hasOwnProperty.call(config, webGMEUrl) === false) {
log('Removing ' + webGMEUrl);
webGMEUrls[webGMEUrl]();
delete webGMEUrls[webGMEUrl];
}
});
}
var workingDirectoryCount = 0;
var rimraf = nodeRequire('rimraf');
rimraf(workingDirectory, function (err) {
if (err) {
log('Could not delete working directory (' + workingDirectory + '), err: ' + err);
process.exit(2);
}
if (!fs.existsSync(workingDirectory)) {
fs.mkdirSync(workingDirectory);
}
readConfig();
fs.watch(configFileName, function () {
setTimeout(readConfig, 200);
}); // setTimeout: likely handle O_TRUNC of config.json
// (though `move config.json.tmp config.json` is preferred)
});
});
}
if (nodeRequire.main === module) {
main();
}
module.exports = main;