System resources sometimes need to shutdown gracefully when exiting. In my case, I have a JSONStream open in node.js. It is serializing objects into JSON and streaming the result to disk, but when the program receives a shutdown signal (e.g. Ctrl-c) the JSON stream is not properly closed and I end up with a file like this:
[
{"id":"myid","value":"myvalue"},
This invalid JSON on disk does not have a closing bracket and causes programs to fail when trying to parse the data.
Let’s prove that we can shutdown JSONStream and other system resources gracefully.
We create an eventemitter and assign it to the global variable COMPOSITE.Process. COMPOSITE is where I put my objects these days, but it could be any name. Next we listen for SIGINT and when we get a SIGINT (Ctrl-c), we emit an ‘exit’ event on Process. Anything that wants to gracefully exit, listens for the ‘exit’ event. When a process wants to do something on exit, they pass a promise to processFn. We won’t exit until all these Promises are resolved. Once they are all resolved, we know we can exit gracefully and therefore call process.exit().
(function(COMPOSITE) {
//Load our dependencies
var util = require('util');
var events = require('events');
var RSVP = require('rsvp');
COMPOSITE.Process = new events.EventEmitter;
//Before we get interrupted, close resources
process.on('SIGINT', function() {
var toShutdown = []
var processFn = function (shutdownProcess) {
toShutdown.push(shutdownProcess)
}
COMPOSITE.Process.emit('exit', processFn);
RSVP.all(toShutdown).then(function() {
console.log('everything shutdown...exiting');
process.exit();
})
})
})(COMPOSITE)
Now to prove Process is intercepting SIGINT (Ctrl-c), we create a test that would fail if Process was not intercepting SIGINT. We show that the test doesn’t fail and therefore is not, not intercepting SIGINT. Or in other words, the test demonstrates Process is intercepting SIGINT.