Skip to content

Commit

Permalink
[fix] Better error message when app appears to be closing too quickly.
Browse files Browse the repository at this point in the history
  • Loading branch information
bmeck committed Jun 15, 2011
1 parent 096c63d commit fea30ac
Showing 1 changed file with 37 additions and 37 deletions.
74 changes: 37 additions & 37 deletions lib/haibu/core/spawner.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* spawner.js: Responsible for checking, downloading, and spawning drones
* spawner.js: Responsible for checking, downloading, and spawning drones
* inside of carapace objects.
*
* (C) 2010, Nodejitsu Inc.
Expand All @@ -10,7 +10,7 @@ var fs = require('fs'),
path = require('path'),
forever = require('forever'),
haibu = require('haibu');

//
// ### Port Management Constants
// TODO (indexzero): Stop using these / make them more intelligent
Expand All @@ -20,15 +20,15 @@ var ports = {},
lastPort = 8000;

//
// ### function Spawner (options)
// #### @options {Object} Options for this instance.
// Constructor function for the Spawner object. Controls the
// low-level aspects of the life-cycle of applications running
// inside of haibu.
// ### function Spawner (options)
// #### @options {Object} Options for this instance.
// Constructor function for the Spawner object. Controls the
// low-level aspects of the life-cycle of applications running
// inside of haibu.
//
var Spawner = exports.Spawner = function (options) {
options = options || {};

this.maxRestart = options.maxRestart;
this.minUptime = options.minUptime;
this.silent = options.silent || false;
Expand All @@ -43,7 +43,7 @@ var Spawner = exports.Spawner = function (options) {
// #### @app {App} Application to bind a port for
// Gets a free port for the requesting application to bind to.
//
// Remark (indexzero): Move this into carapace with shared data for this instance ... ALFRED!!!
// Remark (indexzero): Move this into carapace with shared data for this instance ... ALFRED!!!
//
Spawner.prototype.bindPort = function (app) {
lastPort += 1;
Expand All @@ -53,11 +53,11 @@ Spawner.prototype.bindPort = function (app) {
};

//
// ### function releasePort (port)
// ### function releasePort (port)
// #### @port {int} The port to relase.
// Releases the port if it is bound to an application.
//
// Remark (indexzero): Move this into carapace with shared data for this instance ... ALFRED!!!
// Remark (indexzero): Move this into carapace with shared data for this instance ... ALFRED!!!
//
Spawner.prototype.releasePort = function (port) {
if (ports[port]) {
Expand All @@ -67,7 +67,7 @@ Spawner.prototype.releasePort = function (port) {

return false;
};

//
// ### function trySpawn (app, callback)
// #### @app {App} Application to attempt to spawn on this server.
Expand All @@ -85,12 +85,12 @@ Spawner.prototype.trySpawn = function (app, callback) {
else if (existed) {
return self.spawn(repo, callback);
}

repo.init(function (err, inited) {
if (err) {
return callback(err);
}

self.spawn(repo, callback);
});
});
Expand All @@ -111,37 +111,37 @@ Spawner.prototype.spawnOptions = function (repo, host, port) {
// Reads configuration from haibu, and the repository and calls the appripriate
// internal APIs.
//
Spawner.prototype.spawn = function (repo, callback) {
Spawner.prototype.spawn = function (repo, callback) {
haibu.emit('spawn:setup', 'info', { app: repo.app.id, username: repo.app.user });

var self = this, drone, options, port, result,
foreverOptions, meta, errState, errMsg = '', responded;

port = this.bindPort();

// Setup meta logging information
meta = { app: repo.app.name, user: repo.app.user };

Object.keys(haibu.activePlugins).forEach(function (plugin) {
if (!options && haibu.activePlugins[plugin].spawnOptions) {
options = haibu.activePlugins[plugin].spawnOptions(repo, self.host, port);
}
});

if (!options) {
options = this.spawnOptions(repo, this.host, port);
}

//
// Before we attempt to spawn, let's check if the startPath actually points to a file
// Trapping this specific error is useful as the error indicates an incorrect
// Trapping this specific error is useful as the error indicates an incorrect
// scripts.start property in the package.json
//
fs.stat(repo.startScript, function (err, stats) {
if (err) {
return callback(new Error('package.json error: ' + 'can\'t find starting script: ' + repo.app.scripts.start));
}

haibu.emit('spawn:start', 'info', { options: options.drone.join(' '), app: meta.app, user: meta.user });
foreverOptions = {
minUptime: self.minUptime,
Expand All @@ -151,64 +151,64 @@ Spawner.prototype.spawn = function (repo, callback) {
cwd: repo.homeDir
}
};

foreverOptions.forever = typeof self.maxRestart === 'undefined';
if (typeof self.maxRestart !== 'undefined') {
foreverOptions.max = self.maxRestart;
}

drone = new forever.Monitor(options.carapace, foreverOptions);

//
// TODO (indexzero): This output should be in its own Loggly input (i.e. log.user instead of log.drone)
//
drone.on('stdout', function (data) {
haibu.emit('drone:stdout', 'info', data.toString(), meta);
});

drone.on('stderr', function (data) {
if (!responded) {
errMsg += data + '\n';
}

haibu.emit('drone:stderr', 'error', data.toString(), meta);
});

drone.on('error', function (data) {
haibu.emit('drone:err', 'error', data.toString(), meta);
});


drone.once('start', function (monitor, file, data) {
result = {
monitor: monitor,
process: monitor.child,
drone: data
};

result.drone.port = port;
result.drone.host = self.host;
});

drone.on('exit', function () {
errState = true;
});

//
// Wait briefly to see if the application exits immediately.
//
setTimeout(function () {
var error;
if (errState) {
result.monitor.stop();
error = new Error('Application failed to start on first attempt');
error.message = errMsg;
error = new Error('Application closed too quickly on first attempt');
if(errMsg) error.message = errMsg;
return callback(error);
}

callback(null, result);
}, 200);
drone.start();

drone.start();
});
};

0 comments on commit fea30ac

Please sign in to comment.