Last active
August 13, 2020 04:54
-
-
Save maxnachlinger/dcbdc34a5355eef66fa83106afed6977 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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