Skip to content

Commit

Permalink
t Merge branch 'master' of github.com:balderdashy/sails
Browse files Browse the repository at this point in the history
  • Loading branch information
mikermcneil committed Feb 3, 2016
2 parents fd410f8 + 183f460 commit 62ae56f
Show file tree
Hide file tree
Showing 14 changed files with 415 additions and 169 deletions.
78 changes: 56 additions & 22 deletions lib/app/lower.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,25 @@ var _ = require('lodash');
* @api public
*/

module.exports = function lower(cb) {
module.exports = function lower(options, cb) {
var sails = this;

sails.log.verbose('Lowering sails...');

// Options are optional
if ('function' == typeof options) {
cb = options;
options = null;
}

// Callback is optional
cb = cb || function(err) {
if (err) return sails.log.error(err);
};

options = options || {};
options.delay = options.delay || 100;

// Flag `sails._exiting` as soon as the app has begun to shutdown.
// This may be used by hooks and other parts of core.
// (e.g. to stop handling HTTP requests and prevent ugly error msgs)
Expand Down Expand Up @@ -62,24 +72,37 @@ module.exports = function lower(cb) {
async.series([

function shutdownSockets(cb) {
if (!_.isObject(sails.hooks) || !sails.hooks.sockets) {

// If the sockets hook is disabled, skip this.
// Also skip if the socket server is piggybacking on the main HTTP server, to avoid
// the onClose event possibly being called multiple times (because you can't tell
// socket.io to close without it trying to close the http server). If we're piggybacking
// we'll call sails.io.close in the main "shutdownHTTP" code below.
if (!_.isObject(sails.hooks) || !sails.hooks.sockets || (sails.io.httpServer && sails.hooks.http.server === sails.io.httpServer)) {
return cb();
}

try {
sails.log.verbose('Shutting down socket server...');
var timeOut = setTimeout(cb, 100);
sails.io.server.unref();
sails.io.server.close();
sails.io.server.on('close', function() {
sails.log.verbose('Socket server shut down successfully.');
clearTimeout(timeOut);
cb();
});
timeOut = setTimeout(function() {
sails.io.httpServer.removeListener('close', onClose);
return cb();
}, 100);
sails.io.httpServer.unref();
sails.io.httpServer.once('close', onClose);
sails.io.close();
} catch (e) {
sails.log.verbose("Error occurred closing socket server: ", e);
clearTimeout(timeOut);
cb();
}

function onClose() {
sails.log.verbose('Socket server shut down successfully.');
clearTimeout(timeOut);
cb();
}

},

function shutdownHTTP(cb) {
Expand All @@ -92,25 +115,36 @@ module.exports = function lower(cb) {
try {
sails.log.verbose('Shutting down HTTP server...');

// Give the server 100ms to close all existing connections
// and emit the "close" event. After that, unbind our
// "close" listener and continue (this prevents the cb
// from being called twice).
timeOut = setTimeout(function() {
sails.hooks.http.server.removeListener('close', onClose);
return cb();
}, 100);

// Allow process to exit once this server is closed
sails.hooks.http.server.unref();

// Stop the server from accepting new connections
sails.hooks.http.server.close();
// If we have a socket server and it's piggybacking on the main HTTP server, tell
// socket.io to close now. This may call `.close()` on the HTTP server, which will
// happen again below, but the second synchronous call to .close() will have no
// additional effect. Leaving this as-is in case future versions of socket.io
// DON'T automatically close the http server for you.
if (sails.io && sails.io.httpServer && sails.hooks.http.server === sails.io.httpServer) {
sails.io.close();
}

// If the "hard shutdown" option is on, destroy the server immediately,
// severing all connections
if (options.hardShutdown) {
sails.hooks.http.destroy();
}
// Otherwise just stop the server from accepting new connections,
// and wait options.delay for the existing connections to close
// gracefully before destroying.
else {
timeOut = setTimeout(sails.hooks.http.destroy, options.delay);
sails.hooks.http.server.close();
}

// Wait for the existing connections to close
sails.hooks.http.server.on('close', onClose);
sails.hooks.http.server.once('close', onClose);

} catch (e) {
sails.log.verbose("Error occurred closing HTTP server: ", e);
clearTimeout(timeOut);
cb();
}
Expand Down
4 changes: 2 additions & 2 deletions lib/hooks/blueprints/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -248,7 +248,7 @@ module.exports = function(sails) {
if (config.pluralize) {
baseRouteName = pluralize(baseRouteName);
}

var baseRoute = config.prefix + '/' + baseRouteName;
// Determine base route for RESTful service
// Note that restPrefix will always start with /
Expand Down Expand Up @@ -286,7 +286,7 @@ module.exports = function(sails) {
// -> or implicitly by globalId
// -> or implicitly by controller id
var routeConfig = sails.router.explicitRoutes[controllerId] || {};
var modelFromGlobalId = sails.util.findWhere(sails.models, {globalId: globalId});
var modelFromGlobalId = _.findWhere(sails.models, {globalId: globalId});
var modelId = config.model || routeConfig.model || (modelFromGlobalId && modelFromGlobalId.identity) || controllerId;

// If the orm hook is enabled, it has already been loaded by this time,
Expand Down
2 changes: 1 addition & 1 deletion lib/hooks/csrf/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ module.exports = function(sails) {
}
};
// Add the csrfToken directly to the config'd routes, so that the CORS hook can process it
sails.config.routes = sails.util.extend(csrfRoute, sails.config.routes);
sails.config.routes = _.extend(csrfRoute, sails.config.routes);
},

initialize: function(cb) {
Expand Down
2 changes: 1 addition & 1 deletion lib/hooks/http/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ module.exports = function(sails) {
sails.config.paths.public = path.resolve(sails.config.appPath, sails.config.paths.public);

// Merge in legacy `sails.config.express` object for backwards-compat.
sails.util.defaultsDeep(sails.config.http, sails.config.express||{});
_.defaultsDeep(sails.config.http, sails.config.express||{});

// If no custom middleware order is specified, make sure the default one is used.
// This lets you override default middleware without having to explicitly include the
Expand Down
31 changes: 30 additions & 1 deletion lib/hooks/http/initialize.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,22 @@ module.exports = function(sails) {
var app = sails.hooks.http.app = express();
app.disable('x-powered-by');
// (required by Express 3.x)

// Determine whether or not to create an HTTPS server
var usingSSL = sails.config.ssl === true || (sails.config.ssl.key && sails.config.ssl.cert) || sails.config.ssl.pfx;

// Merge SSL into server options
var serverOptions = sails.config.http.serverOptions || {};
_.extend(serverOptions, sails.config.ssl);

// Lodash 3's _.merge transforms buffers into arrays; if we detect an array, then
// transform it back into a buffer
_.each(['key', 'cert', 'pfx'], function(sslOption) {
if (_.isArray(serverOptions[sslOption])) {
serverOptions[sslOption] = new Buffer(serverOptions[sslOption]);
}
});

// Get the appropriate server creation method for the protocol
var createServer = usingSSL ?
require('https').createServer :
Expand All @@ -48,6 +58,25 @@ module.exports = function(sails) {
sails.hooks.http.server = createServer(serverOptions, sails.hooks.http.app);
} else sails.hooks.http.server = createServer(sails.hooks.http.app);

// Keep track of all connections that come in, so we can destroy
// them later if we want to.
var connections = {};

sails.hooks.http.server.on('connection', function(conn) {
var key = conn.remoteAddress + ':' + conn.remotePort;
connections[key] = conn;
conn.on('close', function() {
delete connections[key];
});
});

// Create a `destroy` method we can use to do a hard shutdown of the server.
sails.hooks.http.destroy = function(cb) {
sails.log.verbose("Destroying http server...");
sails.hooks.http.server.close(cb);
for (var key in connections)
connections[key].destroy();
};

// Configure views if hook enabled
if (sails.hooks.views) {
Expand Down Expand Up @@ -98,7 +127,7 @@ module.exports = function(sails) {
// app.use() the configured express middleware
var defaultMiddleware = require('./middleware/defaults')(sails, app);
installHTTPMiddleware(app, defaultMiddleware, sails);

// Note that it is possible for the configured HTTP middleware stack to be shared with the
// core router built into Sails-- this would make the same stack take effect for all virtual requests
// including sockets. Currently, an abbreviated version of this stack is built-in to `lib/router/`
Expand Down
6 changes: 3 additions & 3 deletions lib/hooks/moduleloader/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ module.exports = function(sails) {
configure: function() {
if (sails.config.moduleLoaderOverride) {
var override = sails.config.moduleLoaderOverride(sails, this);
sails.util.extend(this, override);
_.extend(this, override);
if (override.configure) {
this.configure();
}
Expand Down Expand Up @@ -264,7 +264,7 @@ module.exports = function(sails) {
var env = sails.config.environment;
// Merge the configs, with env/*.js files taking precedence over others, and local.js
// taking precedence over everything
var config = sails.util.merge(
var config = _.merge(
async_data['config/*'],
async_data['config/env/**'],
async_data['config/env/*'],
Expand Down Expand Up @@ -330,7 +330,7 @@ module.exports = function(sails) {
flattenDirectories: true
}, bindToSails(function(err, supplements) {
if (err) {return cb(err);}
return cb(null, sails.util.merge(models, supplements));
return cb(null, _.merge(models, supplements));
}));
});
},
Expand Down
4 changes: 2 additions & 2 deletions lib/hooks/orm/normalize-datastore.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
var path = require('path');
var fs = require('fs');
var Err = require('../../../errors');

var _ = require('lodash');

/**
* normalizeDatastore()
Expand Down Expand Up @@ -85,7 +85,7 @@ module.exports = function howto_normalizeDatastore(sails){
// Defaults connection object to its adapter's defaults
// TODO: pull this out into waterline core
var itsAdapter = sails.adapters[connectionObject.adapter];
connection = sails.util.merge({}, itsAdapter.defaults, connectionObject);
connection = _.merge({}, itsAdapter.defaults, connectionObject);

// If the adapter has a `registerCollection` method, it must be a v0.9.x adapter
if (itsAdapter.registerCollection) {
Expand Down
24 changes: 12 additions & 12 deletions lib/hooks/pubsub/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -453,7 +453,7 @@ module.exports = function(sails) {

if (contexts === true || contexts == '*') {
contexts = this.getAllContexts();
} else if (sails.util.isString(contexts)) {
} else if (_.isString(contexts)) {
contexts = [contexts];
}

Expand Down Expand Up @@ -572,7 +572,7 @@ module.exports = function(sails) {
);
}

if (sails.util.isFunction(this.beforePublishUpdate)) {
if (_.isFunction(this.beforePublishUpdate)) {
this.beforePublishUpdate(id, changes, req, options);
}

Expand Down Expand Up @@ -724,7 +724,7 @@ module.exports = function(sails) {
// Broadcast to the model instance room
this.publish(id, this.identity, 'update', data, socketToOmit);

if (sails.util.isFunction(this.afterPublishUpdate)) {
if (_.isFunction(this.afterPublishUpdate)) {
this.afterPublishUpdate(id, changes, req, options);
}

Expand Down Expand Up @@ -755,7 +755,7 @@ module.exports = function(sails) {
);
}

if (sails.util.isFunction(this.beforePublishDestroy)) {
if (_.isFunction(this.beforePublishDestroy)) {
this.beforePublishDestroy(id, req, options);
}

Expand Down Expand Up @@ -840,7 +840,7 @@ module.exports = function(sails) {

}

if (sails.util.isFunction(this.afterPublishDestroy)) {
if (_.isFunction(this.afterPublishDestroy)) {
this.afterPublishDestroy(id, req, options);
}

Expand Down Expand Up @@ -900,7 +900,7 @@ module.exports = function(sails) {
}

// Lifecycle event
if (sails.util.isFunction(this.beforePublishAdd)) {
if (_.isFunction(this.beforePublishAdd)) {
this.beforePublishAdd(id, alias, idAdded, req);
}

Expand Down Expand Up @@ -961,7 +961,7 @@ module.exports = function(sails) {
}


if (sails.util.isFunction(this.afterPublishAdd)) {
if (_.isFunction(this.afterPublishAdd)) {
this.afterPublishAdd(id, alias, idAdded, req);
}

Expand Down Expand Up @@ -993,7 +993,7 @@ module.exports = function(sails) {
'.publishRemove(id, alias, idRemoved, [socketToOmit])`'
);
}
if (sails.util.isFunction(this.beforePublishRemove)) {
if (_.isFunction(this.beforePublishRemove)) {
this.beforePublishRemove(id, alias, idRemoved, req);
}

Expand Down Expand Up @@ -1043,7 +1043,7 @@ module.exports = function(sails) {

}

if (sails.util.isFunction(this.afterPublishRemove)) {
if (_.isFunction(this.afterPublishRemove)) {
this.afterPublishRemove(id, alias, idRemoved, req);
}

Expand Down Expand Up @@ -1085,15 +1085,15 @@ module.exports = function(sails) {

options = options || {};

if (sails.util.isUndefined(values[this.primaryKey])) {
if (_.isUndefined(values[this.primaryKey])) {
return sails.log.error(
'Invalid usage of publishCreate() :: ' +
'Values must have an `'+this.primaryKey+'`, instead got ::\n' +
util.inspect(values)
);
}

if (sails.util.isFunction(this.beforePublishCreate)) {
if (_.isFunction(this.beforePublishCreate)) {
this.beforePublishCreate(values, req);
}

Expand Down Expand Up @@ -1235,7 +1235,7 @@ module.exports = function(sails) {
this.introduce(values[this.primaryKey]);
}

if (sails.util.isFunction(this.afterPublishCreate)) {
if (_.isFunction(this.afterPublishCreate)) {
this.afterPublishCreate(values, req);
}

Expand Down
Loading

0 comments on commit 62ae56f

Please sign in to comment.