single-child
Spawn a single child process which kills itself on restart.
This was built as a module of listen-spawn, a CLI tool that starts a server and runs a command every time it is pinged; a nodemon over HTTP.
Supported and tested on Linux and Windows.
Getting Started
Install the module with: npm install single-child
Below is a simplified implementation of listen-spawn:
// Inside of app-restarter.js
// Create a new child which starts my app
var SingleChild = require('single-child'),
child = new SingleChild('npm', ['start'], {stdio: [0,1,2]});
// Start my child (and hence my app)
child.start();
// Begin a server which restarts the app when hit
var http = require('http');
http.createServer(function (req, res) {
// We received a ping, restart the child
child.restart();
// Send a NO CONTENT response
res.writeHead(204);
res.end();
}).listen(3000);
// Notify the user the server is up
console.log('App Restarter is listening at http://localhost:3000/');
$ # Inside of a shell
$ # Start and fork our App Restarter
$ node app-restarter.js &
App restarter is listening at http://localhost:3000/
> [email protected] start /home/todd/github/my-app
> echo 'Running app...'
Running app...
$ # Ping the App Restarter (which restarts the app)
$ curl http://localhost:3000/
> [email protected] start /home/todd/github/my-app
> echo 'Running app...'
Running app...
Documentation
SingleChild
acts as a constructor and accepts the same parameters as child_process#spawn with a few extras.
new SingleChild(cmd, [args], [options]);
/**
* Spawn for a single child. Always guarantees only one child exists
* @see child_process.spawn
* @param {String} cmd Command to run
* @param {String[]} [args] Array of arguments to pass with cmd
* @param {Object} [options] Options to pass to `spawn` and for ourselves
* @param {Mixed} [options.killSignal] Signal to pass to `kill` executions
*/
Methods
SingleChild#start
and SingleChild#restart
are how we start children. These are aliases.
child.start([cb]);
child.restart([cb]);
/**
* Stop the currently running child and start a new one
* @param {Function} [cb] Error-first callback that returns *before* the child starts
* @callback {Error|Null} err Error if there was one
* @callback {ChildProcess} child Child that was started. Generated by node's child_process#spawn
*/
SingleChild#stop
and SingleChild#kill
are how we stop children. stop
invokes kill
with SIGINT
rather than allowing for input.
child.stop([cb]);
child.kill([options], [cb]);
/**
* Stop the currently running program
* @param {Object} [options] Options for the kill action
* @param {Mixed} [options.signal] Signal to use when killing
* @param {Function} [cb] Callback to run when process has been killed.
* Receives same params as node's ChildProcess#exit event
*/
Events
SingleChild
fires the following events over its lifecycle:
starting()
is run before a child is spawnedstarted(child)
is run after a child is spawned (does not mean process is running)exited(code, signal)
is run when a child exitskilling(child)
is run before a child is killedkilled(code, signal)
is run after a child is killed
Examples
Below is the same example as before but utilizing events for better notifications.
// Create a new child which starts my app
var SingleChild = require('single-child'),
child = new SingleChild('npm', ['start'], {stdio: [0,1,2]});
// Start my child (and hence my app)
child.start();
// Notify user on start and exit events
child.on('starting', function () {
console.log('Starting app!');
});
child.on('exited', function () {
console.log('App exited!');
});
// Begin a server which restarts the app when hit
var http = require('http');
http.createServer(function (req, res) {
// We received a ping, restart the server
child.restart();
// Send a NO CONTENT response
res.writeHead(204);
res.end();
}).listen(3000);
// Notify the user the server is up
console.log('App restarter is listening at http://localhost:3000/');
$ # Start and fork our App Restarter
$ node app-restarter.js &
App restarter is listening at http://localhost:3000/
Starting app!
> [email protected] start /home/todd/github/my-app
> echo 'Running app...'
Running app...
App exited!
$ # Ping the App Restarter (which restarts the app)
$ curl http://localhost:3000/
Starting app!
> [email protected] start /home/todd/github/my-app
> echo 'Running app...'
Running app...
App exited!
Contributing
In lieu of a formal styleguide, take care to maintain the existing coding style. Add unit tests for any new or changed functionality. Lint via grunt and test via npm test
.
License
Copyright (c) 2013 Todd Wolfson
Licensed under the MIT license.