fix race condition on boot

This commit is contained in:
AJ ONeal 2015-03-29 03:29:40 +00:00
parent 45285b8409
commit 548c48f5bf
1 changed files with 64 additions and 43 deletions

View File

@ -61,6 +61,9 @@ module.exports.create = function (securePort, certsPath, vhostsdir) {
+ "</body>" + "</body>"
+ "</html>" + "</html>"
); );
// for debugging only
throw err;
} }
return next; return next;
@ -79,7 +82,8 @@ module.exports.create = function (securePort, certsPath, vhostsdir) {
return new PromiseA(function (resolve) { return new PromiseA(function (resolve) {
var forEachAsync = require('foreachasync').forEachAsync.create(PromiseA); var forEachAsync = require('foreachasync').forEachAsync.create(PromiseA);
var connect = require('connect'); var connect = require('connect');
var app = connect(); // TODO make lazy
var app = connect().use(require('compression')());
var vhost = require('vhost'); var vhost = require('vhost');
var domainMergeMap = {}; var domainMergeMap = {};
@ -121,14 +125,12 @@ module.exports.create = function (securePort, certsPath, vhostsdir) {
console.log('[log] [once] Preparing mount for', domaininfo.hostname + '/' + domaininfo.dirpathname); console.log('[log] [once] Preparing mount for', domaininfo.hostname + '/' + domaininfo.dirpathname);
domainMergeMap[domaininfo.hostname].mountsMap['/' + domaininfo.dirpathname] = function (req, res, next) { domainMergeMap[domaininfo.hostname].mountsMap['/' + domaininfo.dirpathname] = function (req, res, next) {
function nextify() { function loadThatApp() {
if (appContext) { var time = Date.now();
appContext(req, res, next);
return;
}
console.log('[log] LOADING "' + domaininfo.hostname + '/' + domaininfo.pathname + '"', req.url); console.log('[log] LOADING "' + domaininfo.hostname + '/' + domaininfo.pathname + '"', req.url);
getAppContext(domaininfo).then(function (localApp) { return getAppContext(domaininfo).then(function (localApp) {
console.info((Date.now() - time) + 'ms Loaded ' + domaininfo.hostname + ':' + securePort + '/' + domaininfo.pathname);
//if (localApp.arity >= 2) { /* connect uses .apply(null, arguments)*/ } //if (localApp.arity >= 2) { /* connect uses .apply(null, arguments)*/ }
if ('function' !== typeof localApp) { if ('function' !== typeof localApp) {
localApp = getDummyAppContext(null, "[ERROR] no connect-style export from " + domaininfo.dirname); localApp = getDummyAppContext(null, "[ERROR] no connect-style export from " + domaininfo.dirname);
@ -146,44 +148,42 @@ module.exports.create = function (securePort, certsPath, vhostsdir) {
// TODO redirect GET /favicon.ico to GET (req.headers.referer||'') + /favicon.ico // TODO redirect GET /favicon.ico to GET (req.headers.referer||'') + /favicon.ico
// TODO other common root things - robots.txt, app-icon, etc // TODO other common root things - robots.txt, app-icon, etc
serveFavicon(req, res, handleAppScopedError(domaininfo, req, res, function (req, res) { serveFavicon(req, res, handleAppScopedError(domaininfo, req, res, function (req, res) {
res.writeHead(404); connectContext.static(req, res, handleAppScopedError(domaininfo, req, res, function (req, res) {
res.end( res.writeHead(404);
"<html>" res.end(
+ "<head>" "<html>"
+ '<link rel="icon" href="favicon.ico" />' + "<head>"
+ "</head>" + '<link rel="icon" href="favicon.ico" />'
+ "<body>" + "</head>"
+ "Cannot " + "<body>"
+ encodeURI(req.method) + "Cannot "
+ " 'https://" + encodeURI(req.method)
+ encodeURI(domaininfo.hostname) + " 'https://"
+ '/' + encodeURI(domaininfo.hostname)
+ encodeURI(domaininfo.pathname ? (domaininfo.pathname + '/') : '') + '/'
+ encodeURI(req.url.replace(/^\//, '')) + encodeURI(domaininfo.pathname ? (domaininfo.pathname + '/') : '')
+ "'" + encodeURI(req.url.replace(/^\//, ''))
+ "<br/>" + "'"
+ "<br/>" + "<br/>"
+ "Domain: " + encodeURI(domaininfo.hostname) + "<br/>"
+ "<br/>" + "Domain: " + encodeURI(domaininfo.hostname)
+ "App: " + encodeURI(domaininfo.pathname) + "<br/>"
+ "<br/>" + "App: " + encodeURI(domaininfo.pathname)
+ "Route : " + encodeURI(req.url) + "<br/>"
+ "</body>" + "Route : " + encodeURI(req.url)
+ "</html>" + "</body>"
); + "</html>"
/* );
res.end('{ "error": { "messages": "Route matched ' }));
+ domaininfo.hostname + '/' + domaininfo.pathname
+ ', but was not handled. Forcing hard stop to prevent fallthru." } }');
*/
})); }));
})); }));
} }
try { try {
domainMergeMap[domaininfo.hostname].apps.use('/' + domaininfo.pathname, localAppWrapped); var localConnect = connect();
console.info('Loaded ' + domaininfo.hostname + ':' + securePort + '/' + domaininfo.pathname); localConnect.use(require('connect-query')());
appContext = localAppWrapped; localConnect.use(localAppWrapped);
appContext(req, res, next); domainMergeMap[domaininfo.hostname].apps.use('/' + domaininfo.pathname, localConnect);
return localConnect;
} catch(e) { } catch(e) {
console.error('[ERROR] ' console.error('[ERROR] '
+ domaininfo.hostname + ':' + securePort + domaininfo.hostname + ':' + securePort
@ -199,6 +199,21 @@ module.exports.create = function (securePort, certsPath, vhostsdir) {
}); });
} }
function nextify() {
if (!appContext) {
appContext = loadThatApp();
}
if (!appContext.then) {
appContext(req, res, next);
} else {
appContext.then(function (localConnect) {
appContext = localConnect;
appContext(req, res, next);
});
}
}
if (!serveStatic) { if (!serveStatic) {
serveStatic = require('serve-static'); serveStatic = require('serve-static');
} }
@ -251,7 +266,7 @@ module.exports.create = function (securePort, certsPath, vhostsdir) {
return function (req, res) { return function (req, res) {
res.writeHead(500); res.writeHead(500);
res.end('{ "error": { "message": "' + msg + '" } }'); res.end('{ "error": { "message": "' + msg + '" } }');
} };
} }
function getAppContext(domaininfo) { function getAppContext(domaininfo) {
@ -279,6 +294,9 @@ module.exports.create = function (securePort, certsPath, vhostsdir) {
localApp = PromiseA.resolve(localApp); localApp = PromiseA.resolve(localApp);
} else { } else {
return localApp.catch(function (e) { return localApp.catch(function (e) {
console.error("[ERROR] initialization failed during create() for " + domaininfo.dirname);
console.error(e);
throw e;
return getDummyAppContext(e, "[ERROR] initialization failed during create() for " + domaininfo.dirname); return getDummyAppContext(e, "[ERROR] initialization failed during create() for " + domaininfo.dirname);
}); });
} }
@ -303,6 +321,7 @@ module.exports.create = function (securePort, certsPath, vhostsdir) {
}); });
} }
/*
function hotloadApp(req, res, next) { function hotloadApp(req, res, next) {
var forEachAsync = require('foreachasync').forEachAsync.create(PromiseA); var forEachAsync = require('foreachasync').forEachAsync.create(PromiseA);
var vhost = (req.headers.host || '').split(':')[0]; var vhost = (req.headers.host || '').split(':')[0];
@ -347,8 +366,10 @@ module.exports.create = function (securePort, certsPath, vhostsdir) {
if (!domainMergeMap[domaininfo.hostname]) { if (!domainMergeMap[domaininfo.hostname]) {
// TODO reread directories // TODO reread directories
} }
*/ */ //
/*
} }
*/
// TODO pre-cache these once the server has started? // TODO pre-cache these once the server has started?