From 4f02ccb3b0779c330e326f72726ba0e9e935d354 Mon Sep 17 00:00:00 2001 From: Tyler Renelle Date: Thu, 30 Jan 2014 16:33:25 -0700 Subject: [PATCH] chore(cluster): kill & respawn pids on cluster fail, using domain-middleware --- src/server.js | 223 ++++++++++++++++++++++++++------------------------ src/utils.js | 1 + 2 files changed, 115 insertions(+), 109 deletions(-) diff --git a/src/server.js b/src/server.js index 4bcf9d4fc0..fe81fb76cd 100644 --- a/src/server.js +++ b/src/server.js @@ -1,139 +1,144 @@ // Only do the minimal amount of work before forking just in case of a dyno restart var cluster = require("cluster"); +var _ = require('lodash'); var nconf = require('nconf'); var utils = require('./utils'); utils.setupConfig(); if (cluster.isMaster && (nconf.get('NODE_ENV') == 'development' || nconf.get('NODE_ENV') == 'production')) { - var numCPUs = require('os').cpus().length; + // Fork workers. + _.times(require('os').cpus().length, function(){ + cluster.fork(); + }) - // Fork workers. - for (var i = 0; i < numCPUs; i++) { - cluster.fork(); - } - - cluster.on('exit', function(worker, code, signal) { - cluster.fork(); // replace the dead worker - }); + cluster.on('exit', function(worker, code, signal) { + var w = cluster.fork(); // replace the dead worker + if (nconf.get('NODE_ENV') === 'development') + console.error('[%s] [master:%s] worker:%s disconnect! new worker:%s fork', new Date(), process.pid, worker.process.pid, w.process.pid); + }); } else { - require('coffee-script'); // remove this once we've fully converted over - var express = require("express"); - var http = require("http"); - var path = require("path"); - var domainMiddleware = require('domain-middleware'); - var swagger = require("swagger-node-express"); + require('coffee-script'); // remove this once we've fully converted over + var express = require("express"); + var http = require("http"); + var path = require("path"); + var domainMiddleware = require('domain-middleware'); + var swagger = require("swagger-node-express"); - var middleware = require('./middleware'); + var middleware = require('./middleware'); - var TWO_WEEKS = 1000 * 60 * 60 * 24 * 14; - var app = express(); - var server; + var TWO_WEEKS = 1000 * 60 * 60 * 24 * 14; + var app = express(); + var server = http.createServer(); - // ------------ MongoDB Configuration ------------ - mongoose = require('mongoose'); - require('./models/user'); //load up the user schema - TODO is this necessary? - require('./models/group'); - require('./models/challenge'); - mongoose.connect(nconf.get('NODE_DB_URI'), {auto_reconnect:true}, function(err) { - if (err) throw err; - console.info('Connected with Mongoose'); - }); + // ------------ MongoDB Configuration ------------ + mongoose = require('mongoose'); + require('./models/user'); //load up the user schema - TODO is this necessary? + require('./models/group'); + require('./models/challenge'); + mongoose.connect(nconf.get('NODE_DB_URI'), {auto_reconnect:true}, function(err) { + if (err) throw err; + console.info('Connected with Mongoose'); + }); - // ------------ Passport Configuration ------------ - var passport = require('passport') - var util = require('util') - var FacebookStrategy = require('passport-facebook').Strategy; - // Passport session setup. - // To support persistent login sessions, Passport needs to be able to - // serialize users into and deserialize users out of the session. Typically, - // this will be as simple as storing the user ID when serializing, and finding - // the user by ID when deserializing. However, since this example does not - // have a database of user records, the complete Facebook profile is serialized - // and deserialized. - passport.serializeUser(function(user, done) { - done(null, user); - }); + // ------------ Passport Configuration ------------ + var passport = require('passport') + var util = require('util') + var FacebookStrategy = require('passport-facebook').Strategy; + // Passport session setup. + // To support persistent login sessions, Passport needs to be able to + // serialize users into and deserialize users out of the session. Typically, + // this will be as simple as storing the user ID when serializing, and finding + // the user by ID when deserializing. However, since this example does not + // have a database of user records, the complete Facebook profile is serialized + // and deserialized. + passport.serializeUser(function(user, done) { + done(null, user); + }); - passport.deserializeUser(function(obj, done) { - done(null, obj); - }); + passport.deserializeUser(function(obj, done) { + done(null, obj); + }); - // Use the FacebookStrategy within Passport. - // Strategies in Passport require a `verify` function, which accept - // credentials (in this case, an accessToken, refreshToken, and Facebook - // profile), and invoke a callback with a user object. - passport.use(new FacebookStrategy({ - clientID: nconf.get("FACEBOOK_KEY"), - clientSecret: nconf.get("FACEBOOK_SECRET"), - callbackURL: nconf.get("BASE_URL") + "/auth/facebook/callback" - }, - function(accessToken, refreshToken, profile, done) { - // asynchronous verification, for effect... - //process.nextTick(function () { + // Use the FacebookStrategy within Passport. + // Strategies in Passport require a `verify` function, which accept + // credentials (in this case, an accessToken, refreshToken, and Facebook + // profile), and invoke a callback with a user object. + passport.use(new FacebookStrategy({ + clientID: nconf.get("FACEBOOK_KEY"), + clientSecret: nconf.get("FACEBOOK_SECRET"), + callbackURL: nconf.get("BASE_URL") + "/auth/facebook/callback" + }, + function(accessToken, refreshToken, profile, done) { + // asynchronous verification, for effect... + //process.nextTick(function () { - // To keep the example simple, the user's Facebook profile is returned to - // represent the logged-in user. In a typical application, you would want - // to associate the Facebook account with a user record in your database, - // and return that user instead. - return done(null, profile); - //}); - } - )); + // To keep the example simple, the user's Facebook profile is returned to + // represent the logged-in user. In a typical application, you would want + // to associate the Facebook account with a user record in your database, + // and return that user instead. + return done(null, profile); + //}); + } + )); - // ------------ Server Configuration ------------ - app.set("port", nconf.get('PORT')); + // ------------ Server Configuration ------------ + domainMiddleware({ + server: server, + killTimeout: 3000 + }), - if (!process.env.SUPPRESS) app.use(express.logger("dev")); - app.use(express.compress()); - app.set("views", __dirname + "/../views"); - app.set("view engine", "jade"); - app.use(express.favicon()); - app.use(middleware.cors); - app.use(middleware.forceSSL); - app.use(express.urlencoded()); - app.use(express.json()); - app.use(express.methodOverride()); - //app.use(express.cookieParser(nconf.get('SESSION_SECRET'))); - app.use(express.cookieParser()); - app.use(express.cookieSession({ secret: nconf.get('SESSION_SECRET'), httpOnly: false, cookie: { maxAge: TWO_WEEKS }})); - //app.use(express.session()); + app.set("port", nconf.get('PORT')); - // Initialize Passport! Also use passport.session() middleware, to support - // persistent login sessions (recommended). - app.use(passport.initialize()); - app.use(passport.session()); + if (!process.env.SUPPRESS) app.use(express.logger("dev")); + app.use(express.compress()); + app.set("views", __dirname + "/../views"); + app.set("view engine", "jade"); + app.use(express.favicon()); + app.use(middleware.cors); + app.use(middleware.forceSSL); + app.use(express.urlencoded()); + app.use(express.json()); + app.use(express.methodOverride()); + //app.use(express.cookieParser(nconf.get('SESSION_SECRET'))); + app.use(express.cookieParser()); + app.use(express.cookieSession({ secret: nconf.get('SESSION_SECRET'), httpOnly: false, cookie: { maxAge: TWO_WEEKS }})); + //app.use(express.session()); - app.use(app.router); + // Initialize Passport! Also use passport.session() middleware, to support + // persistent login sessions (recommended). + app.use(passport.initialize()); + app.use(passport.session()); - var maxAge = (nconf.get('NODE_ENV') === 'production') ? 31536000000 : 0; - app.use(express['static'](path.join(__dirname, "/../build"), { maxAge: maxAge })); - app.use(express['static'](path.join(__dirname, "/../public"))); + app.use(app.router); - // development only - //if ("development" === app.get("env")) { - // app.use(express.errorHandler()); - //} + var maxAge = (nconf.get('NODE_ENV') === 'production') ? 31536000000 : 0; + app.use(express['static'](path.join(__dirname, "/../build"), { maxAge: maxAge })); + app.use(express['static'](path.join(__dirname, "/../public"))); - // Custom Directives - app.use(require('./routes/pages').middleware); - app.use(require('./routes/auth').middleware); - var v2 = express(); - app.use('/api/v2', v2); - app.use('/api/v1', require('./routes/apiv1').middleware); - app.use('/export', require('./routes/dataexport').middleware); + // development only + //if ("development" === app.get("env")) { + // app.use(express.errorHandler()); + //} - app.use(utils.errorHandler); + // Custom Directives + app.use(require('./routes/pages').middleware); + app.use(require('./routes/auth').middleware); + var v2 = express(); + app.use('/api/v2', v2); + app.use('/api/v1', require('./routes/apiv1').middleware); + app.use('/export', require('./routes/dataexport').middleware); - require('./routes/apiv2.coffee')(swagger, v2); + app.use(utils.errorHandler); - server = http.createServer(app).listen(app.get("port"), function() { - return console.log("Express server listening on port " + app.get("port")); - }); - app.use(domainMiddleware({ - server: server - //killTimeout: 30000, - })); + require('./routes/apiv2.coffee')(swagger, v2); + + server.on('request', app); + server.listen(app.get("port"), function() { + return console.log("Express server listening on port " + app.get("port")); + }); + + module.exports = server; } \ No newline at end of file diff --git a/src/utils.js b/src/utils.js index e903b3b91c..b8a15cd26d 100644 --- a/src/utils.js +++ b/src/utils.js @@ -79,4 +79,5 @@ module.exports.errorHandler = function(err, req, res, next) { var shortMessage = (err.message.length < 200) ? err.message : err.message.substring(0,100) + err.message.substring(err.message.length-100,err.message.length); res.json(500,{err:shortMessage}); //res.end(err.message); + process.exit(0); } \ No newline at end of file