2019-05-27 10:33:22 -07:00
|
|
|
var cluster = require('cluster');
|
|
|
|
|
|
|
|
|
|
if (cluster.isMaster) {
|
2022-07-03 19:13:50 -06:00
|
|
|
const isWinOS = process.platform == 'win32';
|
|
|
|
|
const instances = (process.argv[2] != null && process.argv[2] != '' && !isNaN(process.argv[2]) && Number.isInteger(parseFloat(process.argv[2])) ? parseInt(process.argv[2]) : require('os').cpus().length);
|
|
|
|
|
|
2021-04-17 13:26:05 -06:00
|
|
|
console.log('Starting cluster with pid: ' + process.pid);
|
|
|
|
|
|
2022-07-03 19:13:50 -06:00
|
|
|
function startWorkers() {
|
|
|
|
|
// create worker instances
|
|
|
|
|
for (var i = 0; i < instances; i += 1)
|
|
|
|
|
cluster.fork();
|
|
|
|
|
}
|
2021-04-17 13:26:05 -06:00
|
|
|
|
2022-07-03 19:13:50 -06:00
|
|
|
function killAllWorkers(isRestart) {
|
2021-04-17 13:26:05 -06:00
|
|
|
// send kill cmd to all workers
|
|
|
|
|
for (var id in cluster.workers) {
|
|
|
|
|
console.log('Worker (' + id + ') shutting down...');
|
2022-04-23 11:28:32 -06:00
|
|
|
|
2022-07-03 19:13:50 -06:00
|
|
|
if (!isWinOS || isRestart) {
|
|
|
|
|
// only kill the worker if not on windows (otherwise an error is displayed) or if the cluster is being restarted
|
2022-04-23 11:28:32 -06:00
|
|
|
process.kill(cluster.workers[id]['process']['pid'], 'SIGINT');
|
2022-07-03 19:13:50 -06:00
|
|
|
}
|
2021-04-17 13:26:05 -06:00
|
|
|
}
|
2022-07-03 19:13:50 -06:00
|
|
|
}
|
2021-04-17 13:26:05 -06:00
|
|
|
|
2022-07-03 19:13:50 -06:00
|
|
|
function waitForWorkerShutdown(isRestart) {
|
|
|
|
|
if (Object.keys(cluster.workers).length > 0) {
|
|
|
|
|
// continue waiting since worker threads are still open
|
|
|
|
|
setTimeout(waitForWorkerShutdown, 100, isRestart);
|
|
|
|
|
} else {
|
|
|
|
|
// all worker threads have closed
|
|
|
|
|
// check if the cluster process should stop or if the workers should be restarted
|
|
|
|
|
if (isRestart) {
|
|
|
|
|
// start new worker threads
|
|
|
|
|
startWorkers();
|
2021-04-17 13:26:05 -06:00
|
|
|
} else {
|
2022-07-03 19:13:50 -06:00
|
|
|
// exit the master process
|
2022-04-23 11:28:32 -06:00
|
|
|
|
|
|
|
|
if (isWinOS) {
|
|
|
|
|
// command line in windows doesn't seem to release itself
|
|
|
|
|
// show a message that the app has finished
|
|
|
|
|
console.log('The application is now safe to close');
|
|
|
|
|
}
|
|
|
|
|
|
2020-12-04 18:51:22 -07:00
|
|
|
process.exit(0);
|
2021-04-17 13:26:05 -06:00
|
|
|
}
|
|
|
|
|
}
|
2022-07-03 19:13:50 -06:00
|
|
|
}
|
2021-04-17 13:26:05 -06:00
|
|
|
|
2022-07-03 19:13:50 -06:00
|
|
|
// ensure workers exit cleanly
|
|
|
|
|
process.on('SIGINT', () => {
|
|
|
|
|
console.log('Cluster shutting down..');
|
2021-04-17 13:26:05 -06:00
|
|
|
|
2022-07-03 19:13:50 -06:00
|
|
|
// send kill cmd to all workers
|
|
|
|
|
killAllWorkers(false);
|
2021-04-17 13:26:05 -06:00
|
|
|
|
2022-07-03 19:13:50 -06:00
|
|
|
// wait for workers to stop
|
|
|
|
|
waitForWorkerShutdown(false);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
startWorkers();
|
2021-04-17 13:26:05 -06:00
|
|
|
|
|
|
|
|
// listen for dying workers
|
|
|
|
|
cluster.on('exit', function (worker, code, signal) {
|
|
|
|
|
if (worker['process']['exitCode'] === 0) {
|
|
|
|
|
console.log('Worker (' + worker['id'] + ') shutdown complete');
|
2022-04-23 11:28:32 -06:00
|
|
|
} else if (signal != 'SIGINT' && worker['process']['exitCode'] !== 0 && worker['process']['exitCode'] !== 999 && worker.exitedAfterDisconnect !== true) {
|
2021-04-17 13:26:05 -06:00
|
|
|
console.log('Cluster restarting...');
|
|
|
|
|
cluster.fork();
|
2019-05-27 10:33:22 -07:00
|
|
|
}
|
|
|
|
|
});
|
2022-07-03 19:13:50 -06:00
|
|
|
|
|
|
|
|
// listen for the restart cmd
|
|
|
|
|
cluster.on('message', function (data, msg) {
|
|
|
|
|
// check if this was the restart cmd
|
|
|
|
|
if (msg != null && msg == 'restart') {
|
|
|
|
|
console.log('Cluster restarting..');
|
|
|
|
|
|
|
|
|
|
// send kill cmd to all workers
|
|
|
|
|
killAllWorkers(true);
|
|
|
|
|
|
|
|
|
|
// wait for workers to stop
|
|
|
|
|
waitForWorkerShutdown(true);
|
|
|
|
|
}
|
|
|
|
|
});
|
2021-03-17 17:54:09 -06:00
|
|
|
} else
|
|
|
|
|
require('./instance');
|