index.js 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  1. "use strict";
  2. const util = require("util");
  3. process.env.NODE_CONFIG_DIR = `${__dirname}/config`;
  4. const config = require("config");
  5. process.on("uncaughtException", (err) => {
  6. if (err.code === "ECONNREFUSED" || err.code === "UNCERTAIN_STATE") return;
  7. console.log(`UNCAUGHT EXCEPTION: ${err.stack}`);
  8. });
  9. const fancyConsole = config.get("fancyConsole");
  10. class ModuleManager {
  11. constructor() {
  12. this.modules = {};
  13. this.modulesInitialized = 0;
  14. this.totalModules = 0;
  15. this.modulesLeft = [];
  16. this.i = 0;
  17. this.lockdown = false;
  18. this.fancyConsole = fancyConsole;
  19. }
  20. addModule(moduleName) {
  21. console.log("add module", moduleName);
  22. const moduleClass = new require(`./logic/${moduleName}`);
  23. this.modules[moduleName] = new moduleClass(moduleName, this);
  24. this.totalModules++;
  25. this.modulesLeft.push(moduleName);
  26. }
  27. initialize() {
  28. if (!this.modules["logger"])
  29. return console.error("There is no logger module");
  30. this.logger = this.modules["logger"];
  31. if (this.fancyConsole) {
  32. this.replaceConsoleWithLogger();
  33. this.logger.reservedLines = Object.keys(this.modules).length + 5;
  34. }
  35. for (let moduleName in this.modules) {
  36. let module = this.modules[moduleName];
  37. if (this.lockdown) break;
  38. module._onInitialize().then(() => {
  39. this.moduleInitialized(moduleName);
  40. });
  41. let dependenciesInitializedPromises = [];
  42. module.dependsOn.forEach((dependencyName) => {
  43. let dependency = this.modules[dependencyName];
  44. dependenciesInitializedPromises.push(
  45. dependency._onInitialize()
  46. );
  47. });
  48. module.lastTime = Date.now();
  49. Promise.all(dependenciesInitializedPromises).then((res, res2) => {
  50. if (this.lockdown) return;
  51. this.logger.info(
  52. "MODULE_MANAGER",
  53. `${moduleName} dependencies have been completed`
  54. );
  55. module._initialize();
  56. });
  57. }
  58. }
  59. async printStatus() {
  60. try {
  61. await Promise.race([
  62. this.logger._onInitialize(),
  63. this.logger._isInitialized(),
  64. ]);
  65. } catch {
  66. return;
  67. }
  68. if (!this.fancyConsole) return;
  69. let colors = this.logger.colors;
  70. const rows = process.stdout.rows;
  71. process.stdout.cursorTo(0, rows - this.logger.reservedLines);
  72. process.stdout.clearScreenDown();
  73. process.stdout.cursorTo(0, rows - this.logger.reservedLines + 2);
  74. process.stdout.write(`${colors.FgYellow}Modules${colors.FgWhite}:\n`);
  75. for (let moduleName in this.modules) {
  76. let module = this.modules[moduleName];
  77. let tabsAmount = Math.max(0, Math.ceil(2 - moduleName.length / 8));
  78. let tabs = Array(tabsAmount)
  79. .fill(`\t`)
  80. .join("");
  81. let timing = module.timeDifferences
  82. .map((timeDifference) => {
  83. return `${colors.FgMagenta}${timeDifference}${colors.FgCyan}ms${colors.FgWhite}`;
  84. })
  85. .join(", ");
  86. let stateColor;
  87. if (module.state === "NOT_INITIALIZED") stateColor = colors.FgWhite;
  88. else if (module.state === "INITIALIZED")
  89. stateColor = colors.FgGreen;
  90. else if (module.state === "LOCKDOWN" && !module.failed)
  91. stateColor = colors.FgRed;
  92. else if (module.state === "LOCKDOWN" && module.failed)
  93. stateColor = colors.FgMagenta;
  94. else stateColor = colors.FgYellow;
  95. process.stdout.write(
  96. `${moduleName}${tabs}${stateColor}${module.state}\t${colors.FgYellow}Stage: ${colors.FgRed}${module.stage}${colors.FgWhite}. ${colors.FgYellow}Timing${colors.FgWhite}: [${timing}]${colors.FgWhite}${colors.FgWhite}. ${colors.FgYellow}Total time${colors.FgWhite}: ${colors.FgRed}${module.totalTimeInitialize}${colors.FgCyan}ms${colors.Reset}\n`
  97. );
  98. }
  99. }
  100. moduleInitialized(moduleName) {
  101. this.modulesInitialized++;
  102. this.modulesLeft.splice(this.modulesLeft.indexOf(moduleName), 1);
  103. this.logger.info(
  104. "MODULE_MANAGER",
  105. `Initialized: ${this.modulesInitialized}/${this.totalModules}.`
  106. );
  107. if (this.modulesLeft.length === 0) this.allModulesInitialized();
  108. }
  109. allModulesInitialized() {
  110. this.logger.success("MODULE_MANAGER", "All modules have started!");
  111. }
  112. aModuleFailed(failedModule) {
  113. this.logger.error(
  114. "MODULE_MANAGER",
  115. `A module has failed, locking down. Module: ${failedModule.name}`
  116. );
  117. this._lockdown();
  118. }
  119. replaceConsoleWithLogger() {
  120. this.oldConsole = {
  121. log: console.log,
  122. debug: console.debug,
  123. info: console.info,
  124. warn: console.warn,
  125. error: console.error,
  126. };
  127. console.log = (...args) =>
  128. this.logger.debug(args.map((arg) => util.format(arg)));
  129. console.debug = (...args) =>
  130. this.logger.debug(args.map((arg) => util.format(arg)));
  131. console.info = (...args) =>
  132. this.logger.debug(args.map((arg) => util.format(arg)));
  133. console.warn = (...args) =>
  134. this.logger.debug(args.map((arg) => util.format(arg)));
  135. console.error = (...args) =>
  136. this.logger.error(
  137. "CONSOLE",
  138. args.map((arg) => util.format(arg))
  139. );
  140. }
  141. replaceLoggerWithConsole() {
  142. console.log = this.oldConsole.log;
  143. console.debug = this.oldConsole.debug;
  144. console.info = this.oldConsole.info;
  145. console.warn = this.oldConsole.warn;
  146. console.error = this.oldConsole.error;
  147. }
  148. _lockdown() {
  149. this.lockdown = true;
  150. for (let moduleName in this.modules) {
  151. let module = this.modules[moduleName];
  152. if (module.lockdownImmune) continue;
  153. module._lockdown();
  154. }
  155. }
  156. }
  157. const moduleManager = new ModuleManager();
  158. module.exports = moduleManager;
  159. moduleManager.addModule("logger");
  160. moduleManager.addModule("io");
  161. moduleManager.addModule("util");
  162. moduleManager.addModule("mongo");
  163. moduleManager.addModule("account");
  164. moduleManager.addModule("accountSchema");
  165. moduleManager.addModule("convertSchema");
  166. moduleManager.initialize();
  167. process.stdin.on("data", function(data) {
  168. if (data.toString() === "lockdown\r\n") {
  169. console.log("Locking down.");
  170. moduleManager._lockdown();
  171. }
  172. });
  173. if (fancyConsole) {
  174. const rows = process.stdout.rows;
  175. for (let i = 0; i < rows; i++) {
  176. process.stdout.write("\n");
  177. }
  178. }