sails
Version:
API-driven framework for building realtime apps, using MVC conventions (based on Express and Socket.io)
174 lines (143 loc) • 6.62 kB
JavaScript
/**
* Module dependencies.
*/
var async = require('async');
var flaverr = require('flaverr');
module.exports = function (sails) {
return function startServer (cb) {
// Used to warn about possible issues if starting the server is taking a long time
var liftAbortTimer;
var liftTimeout = sails.config.liftTimeout || 4000;
// TODO: pull this defaulting into `defaults`
// and also ensure this config is properly documented.
async.auto({
// Start Express server
start: function (next) {
var explicitHost = sails.config.explicitHost;
// If host is explicitly declared, include it in express's listen() call
if (explicitHost) {
sails.log.verbose('Restricting access to explicit host: '+explicitHost);
sails.hooks.http.server.listen(sails.config.port, explicitHost, next);
}
else {
// Listen for error events that may be emitted as the server attempts to start
sails.hooks.http.server.on('error', failedToStart);
sails.hooks.http.server.listen(sails.config.port, function(err) {
// Remove the error listener so future error events emitted by the server
// don't get handled by the "failedToStart" function below.
sails.hooks.http.server.removeListener('error', failedToStart);
return next(err);
});
}
// Start timer in case this takes suspiciously long...
liftAbortTimer = setTimeout(failedToStart, liftTimeout);
// If the server fails to start because of an error, or if it's just taking
// too long, show some troubleshooting notes and bail out.
function failedToStart(err) {
// If this was called because of an actual error, clear the timeout
// so failedToStart doesn't get called again.
if (err) {
clearTimeout(liftAbortTimer);
}
// If sails is exiting already, don't worry about the timer going off.
if (sails._exiting) {return;}
// Figure out if this user is on Windows
var isWin = !!process.platform.match(/^win/);
// If server isn't starting, provide general troubleshooting information,
// sharpened with a few simple heuristics:
console.log('');
if (err) {
sails.log.error('Server failed to start.');
if (err.code) {
sails.log.error('(received error: ' + err.code + ')');
}
} else {
sails.log.error('Server is taking a while to start up (it\'s been ' + (liftTimeout / 1000) + ' seconds).');
}
sails.log.error();
sails.log.error('Troubleshooting tips:');
sails.log.error();
// 0. Just a slow Grunt task
if (sails.hooks.grunt && ! (err && err.code === 'EADDRINUSE')) {
if (process.env.NODE_ENV === 'production') {
sails.log.error(
' -> Do you have a slow Grunt task? You are running in production mode where, by default, tasks are configured to minify the JavaScript and CSS/LESS files in your assets/ directory. Sometimes, these processes can be slow, particularly if you have lots of these types of files.'
);
}
else {
sails.log.error(
' -> Do you have a slow Grunt task, or lots of assets?'
);
}
sails.log.error();
}
// 1. Unauthorized
if (sails.config.port < 1024) {
sails.log.error(
' -> Do you have permission to use port ' + sails.config.port + ' on this system?',
// Don't mention `sudo` to Windows users-- I hear you guys get touchy about that sort of thing :)
(isWin) ? '' : '(you might try `sudo`)'
);
sails.log.error();
}
// 2. Invalid or unauthorized explicitHost configuration.
if (explicitHost) {
sails.log.error(
' -> You might remove your explicit host configuration and try lifting again (you specified',
'`'+explicitHost+'`',
'.)');
sails.log.error();
}
// 3. Something else is running on this port
sails.log.error(
' -> Is something else already running on port', sails.config.port,
(explicitHost ? (' with hostname ' + explicitHost) : '') + '?'
);
sails.log.error();
// 4. invalid explicitHost
if (!explicitHost) {
sails.log.error(
' -> Are you deploying on a platform that requires an explicit hostname,',
'like OpenShift?');
sails.log.error(
' (Try setting the `explicitHost` config to the hostname where the server will be accessible.)'
);
sails.log.error(
' (e.g. `mydomain.com` or `183.24.244.42`)'
);
}
console.log('');
// Lower Sails to do any necessary cleanup
sails.lower(function(){
// Exit with a non-zero value to indicate an error
process.exit(1);
// TODO: For a more graceful shutdown, we should instead consider:
// return next(new Error('blah blah'));
});
}//</failedToStart>
},
verify: ['start', function (results, next) {
var explicitHost = sails.config.explicitHost;
// Check for port conflicts
// Ignore this check if explicit host is set, since other more complicated things might be going on.
if( !explicitHost && !sails.hooks.http.server.address() ) {
var portBusyErrorMsg = '';
portBusyErrorMsg += 'Trying to start server on port ' + sails.config.port + ' but can\'t...';
portBusyErrorMsg += 'Something else is probably running on that port!' + '\n';
portBusyErrorMsg += 'Please disable the other server, or choose a different port and try again.';
sails.log.error(portBusyErrorMsg);
throw flaverr({ name: 'userError', code: 'E_PORT_BUSY' }, new Error(portBusyErrorMsg));
// TODO: For a more graceful shutdown, we should instead consider:
// return next(new Error(portBusyErrorMsg));
}
next();
}]
}, function expressListening (err) {
clearTimeout(liftAbortTimer);
if (err) { return cb(err); }
// Announce that express is now listening on a port
sails.emit('hook:http:listening');
return cb();
});
};
};