Skip to content

Commit

Permalink
[api test doc] Remove deprecated forever.Forever from samples and t…
Browse files Browse the repository at this point in the history
…ests. Added `env` and `cwd` options and associated tests. Some additional code docs and minor style changes
  • Loading branch information
indexzero committed Jun 23, 2011
1 parent c5c9172 commit dfb54be
Show file tree
Hide file tree
Showing 10 changed files with 275 additions and 112 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ You can also use forever from inside your own node.js code.
```javascript
var forever = require('forever');

var child = new (forever.Forever)('your-filename.js', {
var child = new (forever.Monitor)('your-filename.js', {
max: 3,
silent: true,
options: []
Expand Down
1 change: 1 addition & 0 deletions examples/custom-cwd.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
console.log(process.cwd());
4 changes: 4 additions & 0 deletions examples/env-vars.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
console.log(JSON.stringify({
foo: process.env.FOO,
bar: process.env.BAR
}));
4 changes: 2 additions & 2 deletions examples/multiple-processes.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@ var util = require('util'),
forever = require('./../lib/forever'),
script = path.join(__dirname, 'server.js');

var child1 = new (forever.Forever)(script, { 'options': [ "--port=8080"] });
var child1 = new (forever.Monitor)(script, { 'options': [ "--port=8080"] });
child1.start();
util.puts('Forever process running server.js on 8080');

var child2 = new (forever.Forever)(script, { 'options': [ "--port=8081"] });
var child2 = new (forever.Monitor)(script, { 'options': [ "--port=8081"] });
child2.start();
util.puts('Forever process running server.js on 8081');
113 changes: 82 additions & 31 deletions lib/forever/monitor.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,31 +23,52 @@ var sys = require('sys'),
var Monitor = exports.Monitor = function (script, options) {
events.EventEmitter.call(this);

options = options || {};
this.silent = options.silent || false;
this.forever = options.forever || false;
this.command = options.command || 'node';
this.sourceDir = options.sourceDir;
//
// Setup basic configuration options
//
options = options || {};
this.silent = options.silent || false;
this.forever = options.forever || false;
this.uid = options.uid || forever.randomString(24);
this.pidFile = options.pidFile || path.join(forever.config.get('pidPath'), this.uid + '.pid');
this.fvrFile = path.join(forever.config.get('pidPath'), this.uid + '.fvr');
this.max = options.max;
this.childExists = false;
this.times = 0;

//
// Setup restart timing. These options control how quickly forever restarts
// a child process as well as when to kill a "spinning" process
//
this.minUptime = typeof options.minUptime !== 'number' ? 2000 : options.minUptime;
this.spinSleepTime = options.spinSleepTime || null;
this.options = options.options || [];
this.spawnWith = options.spawnWith || null;
this.uid = options.uid || forever.randomString(24);
this.fvrFile = path.join(forever.config.get('pidPath'), this.uid + '.fvr');
this.max = options.max;
this.logFile = options.logFile || path.join(forever.config.get('root'), this.uid + '.log');
this.pidFile = options.pidFile || path.join(forever.config.get('pidPath'), this.uid + '.pid');
this.outFile = options.outFile;
this.errFile = options.errFile;
this.logger = options.logger || new (winston.Logger)({

//
// Setup the command to spawn and the options to pass
// to that command.
//
this.command = options.command || 'node';
this.options = options.options || [];
this.spawnWith = options.spawnWith || {};
this.sourceDir = options.sourceDir;
this.cwd = options.cwd || null;
this.env = options.env || {};

//
// Setup log files and logger for this instance.
//
this.logFile = options.logFile || path.join(forever.config.get('root'), this.uid + '.log');
this.outFile = options.outFile;
this.errFile = options.errFile;
this.logger = options.logger || new (winston.Logger)({
transports: [new winston.transports.Console({ silent: this.silent })]
});

//
// Extend from the winston logger.
//
this.logger.extend(this);

this.childExists = false;

if (Array.isArray(script)) {
this.command = script[0];
this.options = script.slice(1);
Expand All @@ -69,8 +90,6 @@ var Monitor = exports.Monitor = function (script, options) {
if (this.errFile) {
this.stderr = fs.createWriteStream(this.errFile, { flags: 'a+', encoding: 'utf8', mode: 0666 });
}

this.times = 0;
};

// Inherit from events.EventEmitter
Expand Down Expand Up @@ -166,20 +185,16 @@ Monitor.prototype.start = function (restart) {
}

function restartChild() {
self.times++;
process.nextTick(function () {
self.warn('Forever restarting script for ' + self.times + ' time');
self.start(true);
});
}

if (self.forceStop) {
letChildDie();
}
else if (spinning && typeof self.spinSleepTime !== 'number') {
letChildDie();
}
else if (!self.forever && self.times >= self.max) {
self.times++;

if (self.forceStop || (!self.forever && self.times >= self.max)
|| (spinning && typeof self.spinSleepTime !== 'number')) {
letChildDie();
}
else if (spinning) {
Expand Down Expand Up @@ -211,6 +226,9 @@ Monitor.prototype.trySpawn = function () {
}
}

this.spawnWith.cwd = this.cwd || this.spawnWith.cwd;
this.spawnWith.env = this._getEnv();

return spawn(this.command, this.options, this.spawnWith);
};

Expand All @@ -220,6 +238,7 @@ Monitor.prototype.trySpawn = function () {
//
Monitor.prototype.save = function () {
var self = this;

if (!this.running) {
process.nextTick(function () {
self.emit('error', new Error('Cannot save Forever instance that is not running'));
Expand All @@ -238,15 +257,19 @@ Monitor.prototype.save = function () {
uid: this.uid
};

this.childData = childData;
if (this.pidFile) childData.pidFile = this.pidFile;
if (this.outFile) childData.outFile = this.outFile;
if (this.errFile) childData.errFile = this.errFile;
['pidFile', 'outFile', 'errFile', 'env', 'cwd'].forEach(function (key) {
if (self[key]) {
childData[key] = self[key];
}
});

if (this.sourceDir) {
childData.sourceDir = this.sourceDir;
childData.file = childData.file.replace(this.sourceDir + '/', '');
}

this.childData = childData;

fs.writeFile(this.fvrFile, JSON.stringify(childData, null, 2), function (err) {
return err ? self.emit('error', err) : self.emit('save', self.fvrFile, childData);
});
Expand Down Expand Up @@ -319,3 +342,31 @@ Monitor.prototype.kill = function (forceStop) {

return this;
};

//
// ### @private function _getEnv ()
// Returns the environment variables that should be passed along
// to the target process spawned by this instance.
//
Monitor.prototype._getEnv = function () {
var self = this,
extra = Object.keys(this.env),
merged = {};

if (extra.length === 0) {
return process.env;
}

function addKey (key, source) {
merged[key] = source[key]
}

//
// Mixin the key:value pairs from `process.env` and the custom
// environment variables in `this.env`.
//
Object.keys(process.env).forEach(function (k) { addKey(k, process.env) });
extra.forEach(function (k) { addKey(k, self.env) });

return merged;
};
118 changes: 53 additions & 65 deletions test/forever-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,18 @@
*
*/

require.paths.unshift(require('path').join(__dirname, '..', 'lib'));

var sys = require('sys'),
assert = require('assert'),
path = require('path'),
vows = require('vows'),
forever = require('forever');
forever = require('../lib/forever'),
helpers = require('./helpers');

vows.describe('forever').addBatch({
"When using forever": {
"and instance of Forever passed valid options": {
"an instance of forever.Monitor with valid options": {
"should have correct properties set": function () {
var child = new (forever.Forever)('any-file.js', {
var child = new (forever.Monitor)('any-file.js', {
max: 10,
silent: true,
options: []
Expand All @@ -30,67 +29,56 @@ vows.describe('forever').addBatch({
assert.isFunction(child.start);
assert.isFunction(child.save);
assert.isFunction(child.stop);
}
}
},
"running error-on-timer sample three times": {
topic: function () {
var child = new (forever.Forever)(path.join(__dirname, '..', 'examples', 'error-on-timer.js'), {
max: 3,
minUptime: 200,
silent: true,
outFile: 'test/stdout.log',
errFile: 'test/stderr.log',
options: []
});

child.on('exit', this.callback.bind({}, null));
child.start();
},
"should emit 'exit' when completed": function (err, child) {
assert.equal(child.times, 3);
}
},
"non-node usage with a perl one-liner": {
topic: function () {
var child = forever.start([ 'perl', '-le', 'print "moo"' ], {
max: 1,
silent: true,
});
child.on('stdout', this.callback.bind({}, null));
},
"should get back moo": function (err, buf) {
assert.equal(buf.toString(), 'moo\n');
}
},
"attempting to start a script that doesn't exist": {
topic: function () {
var child = forever.start('invalid-path.js', {
max: 1,
silent: true
});
child.on('error', this.callback.bind({}, null));
},
"should throw an error about the invalid file": function (err) {
assert.isNotNull(err);
assert.isTrue(err.message.indexOf('does not exist') !== -1);
}
}
}).addBatch({
"When the tests are over": {
"a call to forever.list()": {
topic: function () {
var that = this;
var tidy = forever.cleanUp(true, true);

tidy.on('cleanUp', function () {
that.callback(null, forever.list(false));
});
},
"should respond with no processes": function (err, procs) {
assert.isNull(err);
assert.isNull(procs);
"running error-on-timer sample three times": helpers.assertTimes(
path.join(__dirname, '..', 'examples', 'error-on-timer.js'),
3,
{
minUptime: 200,
silent: true,
outFile: 'test/stdout.log',
errFile: 'test/stderr.log',
options: []
}
),
"running error-on-timer sample once": helpers.assertTimes(
path.join(__dirname, '..', 'examples', 'error-on-timer.js'),
1,
{
minUptime: 200,
silent: true,
outFile: 'test/stdout.log',
errFile: 'test/stderr.log',
options: []
}
),
"non-node usage with a perl one-liner": {
topic: function () {
var child = forever.start([ 'perl', '-le', 'print "moo"' ], {
max: 1,
silent: true,
});
child.on('stdout', this.callback.bind({}, null));
},
"should get back moo": function (err, buf) {
assert.equal(buf.toString(), 'moo\n');
}
},
"attempting to start a script that doesn't exist": {
topic: function () {
var child = forever.start('invalid-path.js', {
max: 1,
silent: true
});
child.on('error', this.callback.bind({}, null));
},
"should throw an error about the invalid file": function (err) {
assert.isNotNull(err);
assert.isTrue(err.message.indexOf('does not exist') !== -1);
}
}
}
}
}).export(module);
}).addBatch(
helpers.assertEmpty()
).export(module);
Loading

0 comments on commit dfb54be

Please sign in to comment.