Borrowing from the Node.js documentation on Cluster here, a possible approach can be the following:
Main.js
const { fork } = require('child_process');
const WORKER_PATH = 'PATH_TO_WORKER_JS';
const INTERVAL = 10000; // 10 seconds
let CHECKS = 0; // keep count of how many times you check for completion
const worker = fork(WORKER_PATH);
// send message to start the async process
worker.send({ start: true }, err => {
if(err) { // handle error }
});
// check for completion on the worker
setTimeout(() => {
worker.send({ checkIsDone: true }, err => {});
}, INTERVAL);
// listen for message from worker
function checkMsg(msg) {
const { done } = msg;
if(done) {
// async process ended; kill the worker
worker.kill('SIGKILL');
} else {
if(check > 10) {
// checked 10 times for completion, 10 seconds apart;
// process not terminating so force kill
worker.send('SIGKILL');
} else {
// setup another check in 10 seconds
setTimeout(() => {
worker.send({ checkIsDone: true }, err => {});
}, INTERVAL);
}
CHECKS++;
}
}
process.on('message', checkMsg);
Worker.js
let isDone = false;
async function indeterministicProcess() {
// some long computation
// finished
}
process.on('message', msg => {
const { checkIsDone, start } = msg;
if(start) {
// start your async process
interdeterministicProcess().then(() => (isDone = true)).catch(e => console.error(e));
} else if(checkIsDone) {
if(isDone) {
// send done message to master
process.send({ done: true}, err => {});
} else {
process.send({ done: false}, err => {});
}
}
});
This is an approach I have used a few times in the past and has worked for me really well. Hope this gives you some idea on how to implement this for your use case.