1 /*jshint node:true, bitwise:true, indent:2, curly:true, eqeqeq:true, immed:true, latedef:true, newcap:true, noarg:true,
2 regexp:true, undef:true, strict:true, trailing:true, white:true */
3 /*global X:true, XT:true */
6 The X Node.js framework is comprised of 3 major components. The foundation,
7 the database and the server. The foundation can be used on its own. database
8 and server can be used with or without the other but both require the foundation.
10 It is important to note the scoping of the namespace. Unlike most modules that
11 do not expose their scope, X modules and components share the namespace without
12 explicitly exporting it. The global variable X is common to any modules that are
13 required after its initial instantiation
15 It is possible for submodules of the framework to reserve initialization routines
16 until after the framework itself has been fully loaded and initialized. There is
17 an exposed routine in X called `run` that expects a single paramter that is a callback
18 that will be executed in the order it was received. Currently there is no implementation
19 that allows for a module to hook another unless the order of loading is known and
20 the first module emits an event that the second module knows to listen for and receive.
22 There are known limitations in its current implementation in the object hierarchy and
23 some of the convenience mechanisms built-in.
26 //.........................................
27 // Include the foundation that instantiates the
29 require('./foundation');
35 var _ = X._, _path = X.path, sighandler;
37 sighandler = function (signal) {
39 // mostly for logging, make sure anything that wants to know can
40 // easily find why we're shutting down
41 X.SHUTDOWN_SIGNAL = signal;
42 X.io.console(X.StringBuffer.create({color: "blue", prefix: null}),
43 "\n================================================" +
44 "\n%@ CAUGHT - cleaning up before shutting down".f(signal.toUpperCase()) +
45 "\n================================================"
47 // this is a workaround. We want to be able to dictate the exit code. As a convention
48 // we'll say that SIGKILL is the error exit code of 1 and all the rest are the normal
50 X.cleanup(signal === 'SIGKILL');
53 // the first method to run once the framework has been told it is
59 // special case where the desired output requires calling console directly
60 X.io.console(X.StringBuffer.create({ color: 'blue', prefix: null }),
61 "\n================================================" +
62 "\nXTUPLE NODE.JS SERVER" +
63 "\n================================================\n"
66 require("./database");
70 // must explicitly be set to false for it to know you do not want
72 if (X.pidFile !== false) {
74 X.pidFilePath = "%@/pid".f(X.basePath);
75 } else if (X.pidFilePath.indexOf(X.basePath) === -1) {
76 X.pidFilePath = _path.join(X.basePath, X.pidFilePath);
79 X.pidFileName = "%@.pid".f(X.options.processName ? X.options.processName: "node_xt_process");
80 } else if (X.pidFileName.indexOf(".pid") === -1) {
81 X.pidFileName = X.pidFileName.suf(".pid");
84 // if we're allowed to have multiples of this resource executing
85 // simultaneously we need to make the name unique
86 if (X.options.allowMultipleInstances === true) {
87 i = X.pidFileName.indexOf(".pid");
88 sub = X.pidFileName.substring(0, i);
89 X.pidFileName = "%@_%@.pid".f(sub, X.pid);
92 // keep track of the actual pidfile full path
93 X.pidFile = _path.join(X.pidFilePath, X.pidFileName);
95 X.exists(X.pidFile, function (exists) {
96 if (exists && !X.options.allowMultipleInstances) {
97 X.error("Multiple instances are not allowed");
100 // write our pidfile...
101 X.exists(_path.join(X.pidFilePath), function (exists) {
103 X.createDir(X.pidFilePath, X.writePidFile);
113 // give any running process the opportunity to save state
114 // or log as gracefully as possible
115 process.once('exit', _.bind(X.cleanup, X));