|
const EventEmitter = require('events'); |
|
|
|
function gracefulSigint({ forceAttempts } = {}) { |
|
let state = { |
|
isEnabled: false, |
|
isTerminating: false, |
|
isTerminatingForce: forceAttempts >= 0 ? forceAttempts : 5, |
|
}; |
|
let emitter = new EventEmitter(); |
|
let sigintHandler = () => { |
|
if (state.isTerminating) { |
|
if (state.isTerminatingForce > 1) { |
|
--state.isTerminatingForce; |
|
process.stderr.write('\nGot SIGINT, hit it ' + state.isTerminatingForce + ' more times to force terminate.\n'); |
|
} else { |
|
emitter.emit('terminated'); |
|
process.stderr.write('\nGot SIGINT, force terminated.\n'); |
|
process.exit(-1); // eslint-disable-line no-process-exit |
|
} |
|
} else { |
|
process.stderr.write('\nGot SIGINT, will terminate gracefully. Please wait.\n'); |
|
state.isTerminating = true; |
|
emitter.emit('terminating'); |
|
} |
|
}; |
|
let exitHandler = (code) => { |
|
process.stderr.write('\nAbout to exit with code: ' + code + '\n'); |
|
}; |
|
return { |
|
setEnabled: (isEnabled) => { |
|
if (!state) { |
|
return; |
|
} |
|
if (isEnabled === true || isEnabled === undefined) { |
|
state.isEnabled = true; |
|
process.on('SIGINT', sigintHandler); |
|
process.on('exit', exitHandler); |
|
} else { |
|
state.isEnabled = false; |
|
process.removeListener('SIGINT', sigintHandler); |
|
process.removeListener('exit', exitHandler); |
|
} |
|
}, |
|
shouldTerminate: () => (state ? state.isTerminating : false), |
|
addListener: (eventName, callback) => { |
|
if (emitter) { |
|
emitter.addListener(eventName, callback); |
|
} |
|
}, |
|
removeListener: (eventName, callback) => { |
|
if (emitter) { |
|
emitter.removeListener(eventName, callback); |
|
} |
|
}, |
|
destroy: () => { |
|
if (!state) { |
|
return; |
|
} |
|
state = null; |
|
emitter.removeAllListeners(); |
|
emitter = null; |
|
process.removeListener('SIGINT', sigintHandler); |
|
sigintHandler = null; |
|
process.removeListener('exit', exitHandler); |
|
exitHandler = null; |
|
}, |
|
}; |
|
} |
|
|
|
module.exports = { |
|
gracefulSigint, |
|
}; |