var cluster = require('cluster'); if (cluster.isMaster) { 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); console.log('Starting cluster with pid: ' + process.pid); function startWorkers() { // create worker instances for (var i = 0; i < instances; i += 1) cluster.fork(); } function killAllWorkers(isRestart) { // send kill cmd to all workers for (var id in cluster.workers) { console.log('Worker (' + id + ') shutting down...'); if (!isWinOS || isRestart) { // only kill the worker if not on windows (otherwise an error is displayed) or if the cluster is being restarted process.kill(cluster.workers[id]['process']['pid'], 'SIGINT'); } } } 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(); } else { // exit the master process 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'); } process.exit(0); } } } // ensure workers exit cleanly process.on('SIGINT', () => { console.log('Cluster shutting down..'); // send kill cmd to all workers killAllWorkers(false); // wait for workers to stop waitForWorkerShutdown(false); }); startWorkers(); // listen for dying workers cluster.on('exit', function (worker, code, signal) { if (worker['process']['exitCode'] === 0) { console.log('Worker (' + worker['id'] + ') shutdown complete'); } else if (signal != 'SIGINT' && worker['process']['exitCode'] !== 0 && worker['process']['exitCode'] !== 999 && worker.exitedAfterDisconnect !== true) { console.log('Cluster restarting...'); cluster.fork(); } }); // 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); } }); } else require('./instance');