Skip to content

Instantly share code, notes, and snippets.

@maxnachlinger
Last active August 13, 2020 04:54
Show Gist options
  • Save maxnachlinger/dcbdc34a5355eef66fa83106afed6977 to your computer and use it in GitHub Desktop.
Save maxnachlinger/dcbdc34a5355eef66fa83106afed6977 to your computer and use it in GitHub Desktop.
const cluster = require('cluster');
const http = require('http');
const pEachSeries = require('p-each-series');
/*
# start polling via:
while
do
curl http://127.0.0.1:8080
sleep 0.5
done
now kill the main cluster pid
kill <pid>
you can also kill the worker PID and it will restart
kill <workerpid>
*/
const shutdown = 'shutdown';
const startWorker = async () => new Promise((resolve) => {
let resolved = false;
const newWorker = cluster.fork();
newWorker.once('listening', () => resolve());
setTimeout(() => (!resolved && resolve(), resolved = true), 4000);
});
const startWorkers = (amount) => pEachSeries(new Array(amount).fill(), startWorker);
const restartWorkers = () => pEachSeries(Object.keys(cluster.workers), async (id) => {
// bring a new worker up
await startWorker();
// stop the current worker
return new Promise((resolve) => {
let resolved = false;
const worker = cluster.workers[id];
worker.send('shutdown');
worker.disconnect();
worker.once('exit', () => (!resolved && resolve(), resolved = true));
setTimeout(() => (!resolved && resolve(), worker.kill('SIGTERM'), resolved = true), 4000);
});
});
const main = async () => {
if (cluster.isMaster) {
console.log('INFO: Master PID:', process.pid);
await startWorkers(1);
cluster.on('exit', async (worker, code) => {
if (code === 0) {
return;
}
// unexpected failure, start a new worker
console.log('DEBUG: Worker', worker.id, 'died, starting new worker');
await startWorker();
});
// SIGTERM restarts workers
process.on('SIGTERM', async () => await restartWorkers());
} else {
const server = await http.createServer((request, response) => {
if (request.url ==='/crash') {
throw new Error('boom!');
}
response.writeHead(200, {
'Content-Type': 'application/json',
});
response.end(JSON.stringify({id: cluster.worker.id}) + '\n');
}).listen(8080);
process.on('message', (message) => {
if (message === shutdown) {
console.log('DEBUG: worker', cluster.worker.id, 'shutting down....');
server.close(() => {
console.log('DEBUG: worker', cluster.worker.id, 'shut down');
process.exit(0);
});
}
});
console.log(`DEBUG: Worker ${cluster.worker.id} started`);
}
};
main();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment