Skip to content

Commit

Permalink
Refactor to work with newer node versions and change express as well …
Browse files Browse the repository at this point in the history
…as connect and hook.

Allow any files or folders starting with "." inside of module or themes directories. This allows modules or folders of modules to be git submodules.
Add support for 403 error pages. Don't crash if module doesn't have an about.
  • Loading branch information
richtera committed Jul 21, 2012
1 parent ac8afe0 commit 1c4640c
Show file tree
Hide file tree
Showing 24 changed files with 880 additions and 562 deletions.
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ node_modules
modules/downloaded/*
modules/custom
modules/community/*
modules/site
modules/private
media/*
themes/downloaded/*
themes/custom/*
Expand All @@ -15,3 +17,5 @@ docs/coverage.html
*.sock
*.gz
*.sass-cache
themes/community/
themes/private/
162 changes: 126 additions & 36 deletions app-cluster.js
Original file line number Diff line number Diff line change
@@ -1,42 +1,132 @@
// TODO - THIS NEEDS TO BE REPLACED WITH THE NEW Node 0.5+ multi process, see cliftonc/ted
/**
* Master server process
* Initialises a number of instances of the app, based on the number of CPU's it detects
* is available.
*
* First arg is the port
* Second arg is the num worker threads;
*
* e.g. node server 3000 8
*
*/
// Dependencies
var rootpath = process.cwd() + '/',
cluster = require('cluster'),
path = require('path'),
logo = require(path.join(rootpath, 'logo')),
colors = require('colors'),
port = process.env.PORT || 3000,
restarts = 0,
totalWorkers = 0,
runningWorkers = 0;

var argv = processArgs();

launchServer();

/**
* Calipso script for running in clustered mode. Usage: node app-cluster, or
* NODE_ENV=production node app-cluster
* Launch server instance, initially master, then each worker instance is forked.
* All instances share same config.
*/
var cluster = require('cluster');
var port = process.env.PORT || 3000;
var path = __dirname;
var app;
function launchServer() {

// Check if we are the master process
if (cluster.isMaster) {

//require('./app').boot(function (app) {


// Load configuration
var Config = require(rootpath + "lib/core/Configuration"),
config = new Config();

config.init();

// Print the logo
logo.print();

// Set the number of workers
totalWorkers = config.get('server:cluster:workers') || argv.c;

// Fork workers based on num cpus
console.log("Loading ".green + totalWorkers + " workers, please wait ...".green);
for (var i = 0; i < totalWorkers; i++) {
forkWorker();
}

// Log worker death
// TODO : Auto restart with number of retries
cluster.on('death', function(worker) {

console.error('worker ' + worker.pid + ' died ...');

// Manage restarting of workers
if(config.get('server:cluster:restartWorkers')) {
if(restarts > config.get('server:cluster:maximumRestarts')) {
console.error('Maximum number of restarts reached, not restarting this worker.'.red);
} else {
restarts++;
forkWorker();
}
}

});

//});

} else {

// We are a child worker, so bootstrap the app.
require(rootpath + 'app').boot(true, function (app) {

//logger.info("Worker [" + argv.m.cyan + "] with pid " + (process.pid + "").grey + " online.");
app.listen(port);

process.send({ cmd: 'workerStarted', pid: process.pid, port: port });

});

}

}

/**
* Helper function to fork a worker, we need to reset the counter in the master thread
* hence the messaging back, also deal with messaging around job management from worker threads.
*/
function forkWorker() {

var worker = cluster.fork();

worker.on('message', function(msg) {

if (msg.cmd) {

if(msg.cmd == 'workerStarted') {

runningWorkers++;

if(runningWorkers === parseInt(totalWorkers)) {
console.log("Calipso configured for: ".green + (global.process.env.NODE_ENV || 'development') + " environment.".green);
console.log("Calipso server running ".green + runningWorkers + " workers, listening on port: ".green + port);
}

}

}

});

}

/**
* Create an instance of calipso via the normal App,
* Process command line arguments using optimist
*/
require('./app').boot(function (app) {

/**
* TODO: Check to ensure that the logs and pids folders exist before launching
*/

cluster(app)
.set('working directory', path)
.set('socket path', path)
.in('development')
.set('workers', 3)
.use(cluster.logger(path + '/logs', 'debug'))
.use(cluster.debug())
.use(cluster.pidfiles(path + '/pids'))
.use(cluster.stats({ connections: true, lightRequests: true }))
.in('test')
.set('workers', 3)
.use(cluster.logger(path + '/logs', 'warning'))
.use(cluster.pidfiles(path + '/pids'))
.in('production')
.set('workers', 3)
.use(cluster.logger(path + '/logs'))
.use(cluster.pidfiles(path + '/pids'))
.in('all')
.listen(port);


},true);
function processArgs() {
return require('optimist')
.usage('Launch Calipso in Clustered Mode\nUsage: $0')
.describe('c', 'Number of CPUs')
.alias('c', 'cpu')
.default('c', require('os').cpus().length)
.argv;
}
88 changes: 85 additions & 3 deletions app.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,86 @@
*
*/

var req = require('express/lib/request');

var flashFormatters = req.flashFormatters = {
s: function(val){
return String(val);
}
};

/**
* Queue flash `msg` of the given `type`.
*
* Examples:
*
* req.flash('info', 'email sent');
* req.flash('error', 'email delivery failed');
* req.flash('info', 'email re-sent');
* // => 2
*
* req.flash('info');
* // => ['email sent', 'email re-sent']
*
* req.flash('info');
* // => []
*
* req.flash();
* // => { error: ['email delivery failed'], info: [] }
*
* Formatting:
*
* Flash notifications also support arbitrary formatting support.
* For example you may pass variable arguments to `req.flash()`
* and use the %s specifier to be replaced by the associated argument:
*
* req.flash('info', 'email has been sent to %s.', userName);
*
* To add custom formatters use the `exports.flashFormatters` object.
*
* @param {String} type
* @param {String} msg
* @return {Array|Object|Number}
* @api public
*/

function miniMarkdown(str){
return String(str)
.replace(/(__|\*\*)(.*?)\1/g, '<strong>$2</strong>')
.replace(/(_|\*)(.*?)\1/g, '<em>$2</em>')
.replace(/\[([^\]]+)\]\(([^)]+)\)/g, '<a href="$2">$1</a>');
};

req.flash = function(type, msg){
if (this.session === undefined) throw Error('req.flash() requires sessions');
var msgs = this.session.flash = this.session.flash || {};
if (type && msg) {
var i = 2
, args = arguments
, formatters = this.app.flashFormatters || {};
formatters.__proto__ = flashFormatters;
msg = miniMarkdown(msg);
msg = msg.replace(/%([a-zA-Z])/g, function(_, format){
var formatter = formatters[format];
if (formatter) return formatter(utils.escape(args[i++]));
});
return (msgs[type] = msgs[type] || []).push(msg);
} else if (type) {
var arr = msgs[type];
delete msgs[type];
return arr || [];
} else {
this.session.flash = {};
return msgs;
}
};

var sys;
try {
sys = require('util');
} catch (e) {
sys = require('sys');
}

var rootpath = process.cwd() + '/',
path = require('path'),
Expand Down Expand Up @@ -40,8 +120,8 @@ var path = rootpath,
function bootApplication(next) {

// Create our express instance, export for later reference
var app = express.createServer();
app.path = path;
var app = express.createServer ? express.createServer() : express();
app.path = function() { return path };
app.isCluster = false;

// Load configuration
Expand All @@ -55,8 +135,10 @@ function bootApplication(next) {
calipso.defaultTheme = app.config.get('themes:default');

app.use(express.bodyParser());
// Pause requests if they were not parsed to allow PUT and POST with custom mime types
app.use(function (req, res, next) { if (!req._body) { req.pause(); } next(); });
app.use(express.methodOverride());
app.use(express.cookieParser());
app.use(express.cookieParser(app.config.get('session:secret')));
app.use(express.responseTime());

// Create dummy session middleware - tag it so we can later replace
Expand Down
Loading

0 comments on commit 1c4640c

Please sign in to comment.