| 
									
										
										
										
											2015-11-17 08:18:56 +00:00
										 |  |  | 'use strict'; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | module.exports.create = function (opts) { | 
					
						
							|  |  |  |   var id = '0'; | 
					
						
							| 
									
										
										
										
											2015-11-21 12:36:22 +00:00
										 |  |  |   var promiseApp; | 
					
						
							| 
									
										
										
										
											2015-11-17 08:18:56 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-21 12:36:22 +00:00
										 |  |  |   function createAndBindInsecure(message, cb) { | 
					
						
							|  |  |  |     // TODO conditional if 80 is being served by caddy
 | 
					
						
							|  |  |  |     require('../lib/insecure-server').create(message.conf.externalPort, message.conf.insecurePort, message, function (err, webserver) { | 
					
						
							|  |  |  |       console.info("#" + id + " Listening on http://" + webserver.address().address + ":" + webserver.address().port, '\n'); | 
					
						
							| 
									
										
										
										
											2015-11-17 08:18:56 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-21 12:36:22 +00:00
										 |  |  |       // we are returning the promise result to the caller
 | 
					
						
							|  |  |  |       return cb(null, webserver, null, message); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   function createAndBindServers(message, cb) { | 
					
						
							|  |  |  |     // NOTE that message.conf[x] will be overwritten when the next message comes in
 | 
					
						
							|  |  |  |     require('../lib/local-server').create(message.conf.certPaths, message.conf.localPort, message, function (err, webserver) { | 
					
						
							| 
									
										
										
										
											2015-11-17 08:18:56 +00:00
										 |  |  |       if (err) { | 
					
						
							|  |  |  |         console.error('[ERROR] worker.js'); | 
					
						
							|  |  |  |         console.error(err.stack); | 
					
						
							|  |  |  |         throw err; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-21 12:36:22 +00:00
										 |  |  |       console.info("#" + id + " Listening on " + message.conf.protocol + "://" + webserver.address().address + ":" + webserver.address().port, '\n'); | 
					
						
							| 
									
										
										
										
											2015-11-17 08:18:56 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-21 12:36:22 +00:00
										 |  |  |       // we don't need time to pass, just to be able to return
 | 
					
						
							|  |  |  |       process.nextTick(function () { | 
					
						
							|  |  |  |         createAndBindInsecure(message, cb); | 
					
						
							|  |  |  |       }); | 
					
						
							| 
									
										
										
										
											2015-11-17 08:18:56 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-21 12:36:22 +00:00
										 |  |  |       // we are returning the promise result to the caller
 | 
					
						
							|  |  |  |       return cb(null, null, webserver, message); | 
					
						
							|  |  |  |     }); | 
					
						
							| 
									
										
										
										
											2015-11-17 08:18:56 +00:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   //
 | 
					
						
							|  |  |  |   // Worker Mode
 | 
					
						
							|  |  |  |   //
 | 
					
						
							|  |  |  |   function waitForConfig(message) { | 
					
						
							| 
									
										
										
										
											2015-11-28 05:57:07 +00:00
										 |  |  |     if ('walnut.init' !== message.type) { | 
					
						
							| 
									
										
										
										
											2015-11-17 08:18:56 +00:00
										 |  |  |       console.warn('[Worker] 0 got unexpected message:'); | 
					
						
							|  |  |  |       console.warn(message); | 
					
						
							|  |  |  |       return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     process.removeListener('message', waitForConfig); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // NOTE: this callback must return a promise for an express app
 | 
					
						
							| 
									
										
										
										
											2015-11-21 12:36:22 +00:00
										 |  |  |     createAndBindServers(message, function (err, insecserver, webserver, oldMessage) { | 
					
						
							|  |  |  |       // TODO deep merge new message into old message
 | 
					
						
							|  |  |  |       Object.keys(message.conf).forEach(function (key) { | 
					
						
							|  |  |  |         oldMessage.conf[key] = message.conf[key]; | 
					
						
							|  |  |  |       }); | 
					
						
							| 
									
										
										
										
											2015-11-17 08:18:56 +00:00
										 |  |  |       var PromiseA = require('bluebird'); | 
					
						
							| 
									
										
										
										
											2015-11-21 12:36:22 +00:00
										 |  |  |       if (promiseApp) { | 
					
						
							|  |  |  |         return promiseApp; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       promiseApp = new PromiseA(function (resolve) { | 
					
						
							| 
									
										
										
										
											2015-11-17 08:18:56 +00:00
										 |  |  |         function initWebServer(srvmsg) { | 
					
						
							| 
									
										
										
										
											2015-11-28 05:57:07 +00:00
										 |  |  |           if ('walnut.webserver.onrequest' !== srvmsg.type) { | 
					
						
							| 
									
										
										
										
											2015-11-17 08:18:56 +00:00
										 |  |  |             console.warn('[Worker] 1 got unexpected message:'); | 
					
						
							|  |  |  |             console.warn(srvmsg); | 
					
						
							|  |  |  |             return; | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           process.removeListener('message', initWebServer); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           resolve(require('../lib/worker').create(webserver, srvmsg)); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-28 05:57:07 +00:00
										 |  |  |         process.send({ type: 'walnut.webserver.listening' }); | 
					
						
							| 
									
										
										
										
											2015-11-17 08:18:56 +00:00
										 |  |  |         process.on('message', initWebServer); | 
					
						
							|  |  |  |       }).then(function (app) { | 
					
						
							|  |  |  |         console.info('[Worker Ready]'); | 
					
						
							|  |  |  |         return app; | 
					
						
							|  |  |  |       }); | 
					
						
							| 
									
										
										
										
											2015-11-21 12:36:22 +00:00
										 |  |  |       return promiseApp; | 
					
						
							| 
									
										
										
										
											2015-11-17 08:18:56 +00:00
										 |  |  |     }); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   //
 | 
					
						
							|  |  |  |   // Standalone Mode
 | 
					
						
							|  |  |  |   //
 | 
					
						
							|  |  |  |   if (opts) { | 
					
						
							|  |  |  |     // NOTE: this callback must return a promise for an express app
 | 
					
						
							| 
									
										
										
										
											2015-11-21 12:36:22 +00:00
										 |  |  |     createAndBindServers(opts, function (err, insecserver, webserver/*, message*/) { | 
					
						
							| 
									
										
										
										
											2015-11-17 08:18:56 +00:00
										 |  |  |       var PromiseA = require('bluebird'); | 
					
						
							| 
									
										
										
										
											2015-11-21 12:36:22 +00:00
										 |  |  |       if (promiseApp) { | 
					
						
							|  |  |  |         return promiseApp; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       promiseApp = new PromiseA(function (resolve) { | 
					
						
							| 
									
										
										
										
											2015-11-17 08:18:56 +00:00
										 |  |  |         opts.getConfig(function (srvmsg) { | 
					
						
							|  |  |  |           resolve(require('../lib/worker').create(webserver, srvmsg)); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |       }).then(function (app) { | 
					
						
							|  |  |  |         console.info('[Standalone Ready]'); | 
					
						
							|  |  |  |         return app; | 
					
						
							|  |  |  |       }); | 
					
						
							| 
									
										
										
										
											2015-11-21 12:36:22 +00:00
										 |  |  |       return promiseApp; | 
					
						
							| 
									
										
										
										
											2015-11-17 08:18:56 +00:00
										 |  |  |     }); | 
					
						
							|  |  |  |   } else { | 
					
						
							|  |  |  |     // we are in cluster mode, as opposed to standalone mode
 | 
					
						
							|  |  |  |     id = require('cluster').worker.id.toString(); | 
					
						
							|  |  |  |     // We have to wait to get the configuration from the master process
 | 
					
						
							|  |  |  |     // before we can start our webserver
 | 
					
						
							|  |  |  |     console.info('[Worker #' + id + '] online!'); | 
					
						
							|  |  |  |     process.on('message', waitForConfig); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   //
 | 
					
						
							|  |  |  |   // Debugging
 | 
					
						
							|  |  |  |   //
 | 
					
						
							|  |  |  |   process.on('exit', function (code) { | 
					
						
							|  |  |  |     // only sync code can run here
 | 
					
						
							|  |  |  |     console.info('uptime:', process.uptime()); | 
					
						
							|  |  |  |     console.info(process.memoryUsage()); | 
					
						
							|  |  |  |     console.info('[exit] process.exit() has been called (or master has killed us).'); | 
					
						
							|  |  |  |     console.info(code); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  |   process.on('beforeExit', function () { | 
					
						
							|  |  |  |     // async can be scheduled here
 | 
					
						
							|  |  |  |     console.info('[beforeExit] Event Loop is empty. Process will end.'); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  |   process.on('unhandledRejection', function (err) { | 
					
						
							|  |  |  |     // this should always throw
 | 
					
						
							|  |  |  |     // (it means somewhere we're not using bluebird by accident)
 | 
					
						
							|  |  |  |     console.error('[caught] [unhandledRejection]'); | 
					
						
							|  |  |  |     console.error(Object.keys(err)); | 
					
						
							|  |  |  |     console.error(err); | 
					
						
							|  |  |  |     console.error(err.stack); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  |   process.on('rejectionHandled', function (msg) { | 
					
						
							|  |  |  |     console.error('[rejectionHandled]'); | 
					
						
							|  |  |  |     console.error(msg); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | }; |