cryptonote-universal-pool/init.js

254 lines
6.8 KiB
JavaScript

var fs = require('fs');
var cluster = require('cluster');
var os = require('os');
var redis = require('redis');
require('./lib/configReader.js');
require('./lib/logger.js');
global.redisClient = redis.createClient(config.redis.port, config.redis.host);
if (cluster.isWorker){
switch(process.env.workerType){
case 'pool':
require('./lib/pool.js');
break;
case 'blockUnlocker':
require('./lib/blockUnlocker.js');
break;
case 'paymentProcessor':
require('./lib/paymentProcessor.js');
break;
case 'api':
require('./lib/api.js');
break;
case 'cli':
require('./lib/cli.js');
break
case 'chartsDataCollector':
require('./lib/chartsDataCollector.js');
break
}
return;
}
var logSystem = 'master';
require('./lib/exceptionWriter.js')(logSystem);
var singleModule = (function(){
var validModules = ['pool', 'api', 'unlocker', 'payments', 'chartsDataCollector'];
for (var i = 0; i < process.argv.length; i++){
if (process.argv[i].indexOf('-module=') === 0){
var moduleName = process.argv[i].split('=')[1];
if (validModules.indexOf(moduleName) > -1)
return moduleName;
log('error', logSystem, 'Invalid module "%s", valid modules: %s', [moduleName, validModules.join(', ')]);
process.exit();
}
}
})();
(function init(){
checkRedisVersion(function(){
if (singleModule){
log('info', logSystem, 'Running in single module mode: %s', [singleModule]);
switch(singleModule){
case 'pool':
spawnPoolWorkers();
break;
case 'unlocker':
spawnBlockUnlocker();
break;
case 'payments':
spawnPaymentProcessor();
break;
case 'api':
spawnApi();
break;
case 'chartsDataCollector':
spawnChartsDataCollector();
break;
}
}
else{
spawnPoolWorkers();
spawnBlockUnlocker();
spawnPaymentProcessor();
spawnApi();
spawnChartsDataCollector();
}
spawnCli();
});
})();
function checkRedisVersion(callback){
redisClient.info(function(error, response){
if (error){
log('error', logSystem, 'Redis version check failed');
return;
}
var parts = response.split('\r\n');
var version;
var versionString;
for (var i = 0; i < parts.length; i++){
if (parts[i].indexOf(':') !== -1){
var valParts = parts[i].split(':');
if (valParts[0] === 'redis_version'){
versionString = valParts[1];
version = parseFloat(versionString);
break;
}
}
}
if (!version){
log('error', logSystem, 'Could not detect redis version - must be super old or broken');
return;
}
else if (version < 2.6){
log('error', logSystem, "You're using redis version %s the minimum required version is 2.6. Follow the damn usage instructions...", [versionString]);
return;
}
callback();
});
}
function spawnPoolWorkers(){
if (!config.poolServer || !config.poolServer.enabled || !config.poolServer.ports || config.poolServer.ports.length === 0) return;
if (config.poolServer.ports.length === 0){
log('error', logSystem, 'Pool server enabled but no ports specified');
return;
}
var numForks = (function(){
if (!config.poolServer.clusterForks)
return 1;
if (config.poolServer.clusterForks === 'auto')
return os.cpus().length;
if (isNaN(config.poolServer.clusterForks))
return 1;
return config.poolServer.clusterForks;
})();
var poolWorkers = {};
var createPoolWorker = function(forkId){
var worker = cluster.fork({
workerType: 'pool',
forkId: forkId
});
worker.forkId = forkId;
worker.type = 'pool';
poolWorkers[forkId] = worker;
worker.on('exit', function(code, signal){
log('error', logSystem, 'Pool fork %s died, spawning replacement worker...', [forkId]);
setTimeout(function(){
createPoolWorker(forkId);
}, 2000);
}).on('message', function(msg){
switch(msg.type){
case 'banIP':
Object.keys(cluster.workers).forEach(function(id) {
if (cluster.workers[id].type === 'pool'){
cluster.workers[id].send({type: 'banIP', ip: msg.ip});
}
});
break;
}
});
};
var i = 1;
var spawnInterval = setInterval(function(){
createPoolWorker(i.toString());
i++;
if (i - 1 === numForks){
clearInterval(spawnInterval);
log('info', logSystem, 'Pool spawned on %d thread(s)', [numForks]);
}
}, 10);
}
function spawnBlockUnlocker(){
if (!config.blockUnlocker || !config.blockUnlocker.enabled) return;
var worker = cluster.fork({
workerType: 'blockUnlocker'
});
worker.on('exit', function(code, signal){
log('error', logSystem, 'Block unlocker died, spawning replacement...');
setTimeout(function(){
spawnBlockUnlocker();
}, 2000);
});
}
function spawnPaymentProcessor(){
if (!config.payments || !config.payments.enabled) return;
var worker = cluster.fork({
workerType: 'paymentProcessor'
});
worker.on('exit', function(code, signal){
log('error', logSystem, 'Payment processor died, spawning replacement...');
setTimeout(function(){
spawnPaymentProcessor();
}, 2000);
});
}
function spawnApi(){
if (!config.api || !config.api.enabled) return;
var worker = cluster.fork({
workerType: 'api'
});
worker.on('exit', function(code, signal){
log('error', logSystem, 'API died, spawning replacement...');
setTimeout(function(){
spawnApi();
}, 2000);
});
}
function spawnCli(){
}
function spawnChartsDataCollector(){
if (!config.charts) return;
var worker = cluster.fork({
workerType: 'chartsDataCollector'
});
worker.on('exit', function(code, signal){
log('error', logSystem, 'chartsDataCollector died, spawning replacement...');
setTimeout(function(){
spawnChartsDataCollector();
}, 2000);
});
}