spinner
Spawns child processes with dynamic port allocation and other goodies. Sort of like forever but with a few more features.
- Allocates ports dynamically and hands them over child processes via the
PORT
environment variable - Respawn processes that decided to go to bed
- Stateless API for a pretty stateful module (uses fsmjs).
More to come...
- Monitor a file/directory and restart the child if changed
- If a child was not 'touched' for some time, automatically stop it
- Keep a child process running for a while when spawning a new one due
to an update (tandem mode).
$ npm install spinner
var request = require('request');
var spinner = require('spinner').createSpinner();
spinner.start('myapp', function(err, port) {
if (err) return console.error(err);
request('http://localhost:' + port, function(err, res, body) {
console.log('response:', body);
spinner.stopall();
});
});
Output:
$ node basic.js
[myapp] starting myapp
[myapp] looking for an available port in the range: [ 7000, 7999 ]
[myapp] found port 7000
[myapp] spawn /usr/local/bin/node [ 'myapp' ]
[myapp] waiting for port 7000 to be bound
[myapp] checking status of port 7000 tries left: 10
[myapp] status is closed
[myapp] checking status of port 7000 tries left: 9
[myapp] status is open
[myapp] port 7000 opened successfuly
[myapp] clearing wait timeout
response: this is a sample app
[myapp] stopping
[myapp] exited with status 1
[myapp] cleaning up
API
createSpinner()
Returns a spinner. Within a spinner namespace, child processes are identified by name and only
a single child can exists for every name.
This means that if I call spinner.start('foo')
twice, only a single child will be spawned. The second call will return the same port.
spinner.start(options, callback)
name: 'foofoo',
command: process.execPath,
args: [ './myapp.js' ],
env: { myenv: '1234' },
logger: console,
timeout: 5,
attempts: 3,
stopTimeout: 30,
monitor: './lazykiller.js',
stdout: process.stdout,
stderr: process.stderr,
The argument callback
is function(err, port)
where port
is the port number allocated for this child process and set in it's PORT
environment variable (in node.js: process.env.PORT
). If the child could not be started or if it did not bind to the port in the alloted timeout
, err
will indicate that with an Error
object.
spinner.start(script, callback)
A short form for spinner.start()
where script
is used as the first argument to the node engine prescribed in process.execPath
and also used as the name of the child.
Monitor is also set to point to the script, so if it changes, the child will be
restarted.
spinner.stop(name, callback)
Stops the child keyed name
. callback
is function(err)
.
Spinner sends SIGTERM
and after stopTimeout
passes, sends SIGKILL
.
spinner.stopall(callback)
Stops all the child processes maintained by this spinner.
callback
is function(err)
spinner.get(name)
Returns information about a child process named name
. The information includes the options
used to start the child process and a state
property indicating the current state of the
child.
Possible states are:
- stopped - Child is stopped.
- starting - Child is being spawned and waiting for port to be bound to.
- started - Child is started.
- stopping - Child is being stopped.
- faulted - Child is faulted. That is, the alloted number of start requests failed.
- restart - Child is being restarted.
spinner.list()
Returns the list of child processes maintained by this spinner. The result is a hash
keyed by the child name and contains the details from spinner.get()
.
Event: 'started'
function(port) {}
Emitted after the child process has been started and bound to port
. This means it can
be accessed from now on via { host: 'localhost', port: port }
.
Event: 'stopped'
function() {}
Emitted after the child process has been stopped.
Event: 'restarted'
function(port) {}
Emitted after the child process has been restarted (either due to a file change or due
to a crash).
Event: 'error'
function(e) {}
Emitted when an error occured while starting the child process.
License
MIT
Contributors
Originally forked from forked from nploy by George Stagas (@stagas), but since I had to work out the crazy state machine, not much code of nploy
let. Neverthess, it's an awesome lib.