main.ts 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273
  1. import * as readline from "node:readline";
  2. import ModuleManager from "./ModuleManager";
  3. import LogBook from "./LogBook";
  4. const logBook = new LogBook();
  5. process.removeAllListeners("uncaughtException");
  6. process.on("uncaughtException", err => {
  7. if (err.name === "ECONNREFUSED" || err.name === "UNCERTAIN_STATE") return;
  8. logBook.log({
  9. message: err.message || err,
  10. type: "error",
  11. category: "uncaught-exceptions",
  12. data: {
  13. error: err.message
  14. ? {
  15. cause: err.cause,
  16. name: err.name,
  17. stack: err.stack
  18. }
  19. : err
  20. }
  21. });
  22. });
  23. const moduleManager = new ModuleManager(logBook);
  24. moduleManager.startup();
  25. // TOOD remove, or put behind debug option
  26. // eslint-disable-next-line
  27. // @ts-ignore
  28. global.moduleManager = moduleManager;
  29. // eslint-disable-next-line
  30. // @ts-ignore
  31. global.rs = () => {
  32. process.exit();
  33. };
  34. // const interval = setInterval(() => {
  35. // moduleManager
  36. // .runJob("stations", "addToQueue", { songId: "TestId" })
  37. // .catch(() => {});
  38. // moduleManager
  39. // .runJob("stations", "addA", {}, { priority: 5 })
  40. // .catch(() => {});
  41. // moduleManager
  42. // .runJob("others", "doThing", { test: "Test", test2: 123 })
  43. // .catch(() => {});
  44. // }, 40);
  45. // setTimeout(() => {
  46. // clearTimeout(interval);
  47. // }, 3000);
  48. setTimeout(async () => {
  49. const _id = "6371212daf4e9f8fb14444b2";
  50. // logBook.log("Find with no projection");
  51. // await moduleManager
  52. // .runJob("data", "find", {
  53. // collection: "abc",
  54. // filter: {
  55. // _id
  56. // }
  57. // })
  58. // .then(console.log)
  59. // .catch(console.error);
  60. // logBook.log("Find with no projection, and a more advanced filter");
  61. // await moduleManager
  62. // .runJob("data", "find", {
  63. // collection: "abc",
  64. // filter: {
  65. // "autofill.enabled": true
  66. // }
  67. // })
  68. // .then(console.log)
  69. // .catch(console.error);
  70. // logBook.log("Find with array projection");
  71. // await moduleManager
  72. // .runJob("data", "find", {
  73. // collection: "abc",
  74. // filter: {
  75. // _id
  76. // },
  77. // projection: ["name"]
  78. // })
  79. // .then(console.log)
  80. // .catch(console.error);
  81. // logBook.log("Find with object boolean projection");
  82. // await moduleManager
  83. // .runJob("data", "find", {
  84. // collection: "abc",
  85. // filter: {
  86. // _id
  87. // },
  88. // projection: { name: true },
  89. // limit: 1
  90. // })
  91. // .then(console.log)
  92. // .catch(console.error);
  93. // logBook.log("Find with object number projection");
  94. // await moduleManager
  95. // .runJob("data", "find", {
  96. // collection: "abc",
  97. // filter: {
  98. // _id
  99. // },
  100. // projection: { name: 1 }
  101. // })
  102. // .then(console.log)
  103. // .catch(console.error);
  104. // logBook.log("Find with object number projection");
  105. // await moduleManager
  106. // .runJob("data", "find", {
  107. // collection: "abc",
  108. // filter: {
  109. // _id
  110. // },
  111. // projection: { "autofill.enabled": true }
  112. // })
  113. // .then(console.log)
  114. // .catch(console.error);
  115. // logBook.log("Find for testing casting");
  116. // await moduleManager
  117. // .runJob("data", "find", {
  118. // collection: "abc",
  119. // filter: {
  120. // // "songs._id": "6371212daf4e9f8fb14444b0"
  121. // // "songs._id": "6371212daf4e9f8fb14444b2"
  122. // // songs: {
  123. // // _id: "6371212daf4e9f8fb14444b0"
  124. // // }
  125. // // songs: {
  126. // // randomProperty: "6371212daf4e9f8fb14444b0"
  127. // // }
  128. // "songs.obj.test": "6371212daf4e9f8fb14444b0"
  129. // },
  130. // // projection: {
  131. // // // songs: true,
  132. // // // someNumbers: false
  133. // // },
  134. // limit: 1
  135. // })
  136. // .then(console.log)
  137. // .catch(console.error);
  138. }, 0);
  139. const rl = readline.createInterface({
  140. input: process.stdin,
  141. output: process.stdout,
  142. completer: (command: string) => {
  143. const parts = command.split(" ");
  144. const commands = ["eval "];
  145. if (parts.length === 1) {
  146. const hits = commands.filter(c => c.startsWith(parts[0]));
  147. return [hits.length ? hits : commands, command];
  148. }
  149. return [];
  150. },
  151. removeHistoryDuplicates: true
  152. });
  153. const shutdown = async () => {
  154. if (rl) {
  155. rl.removeAllListeners();
  156. rl.close();
  157. }
  158. await moduleManager.shutdown().catch(() => process.exit(1));
  159. process.exit(0);
  160. };
  161. process.on("SIGINT", shutdown);
  162. process.on("SIGQUIT", shutdown);
  163. process.on("SIGTERM", shutdown);
  164. const runCommand = (line: string) => {
  165. const [command, ...args] = line.split(" ");
  166. switch (command) {
  167. case "help": {
  168. console.log("Commands:");
  169. console.log("status");
  170. console.log("stats");
  171. console.log("queue");
  172. console.log("active");
  173. console.log("eval");
  174. console.log("debug");
  175. console.log("log");
  176. break;
  177. }
  178. case "status": {
  179. console.log("Module Manager Status:");
  180. console.table(moduleManager.getStatus());
  181. console.log("Job Queue Status:");
  182. console.table(moduleManager.getJobsStatus());
  183. break;
  184. }
  185. case "stats": {
  186. console.log("Job Queue Stats:");
  187. console.table(moduleManager.getJobsStats());
  188. break;
  189. }
  190. case "queue": {
  191. const queueStatus = moduleManager.getQueueStatus().queue;
  192. if (queueStatus.length === 0)
  193. console.log("There are no jobs in the queue.");
  194. else
  195. console.log(
  196. `There are ${queueStatus.length} jobs in the queue.`
  197. );
  198. console.table(queueStatus);
  199. break;
  200. }
  201. case "active": {
  202. const activeStatus = moduleManager.getQueueStatus().active;
  203. if (activeStatus.length === 0)
  204. console.log("There are no active jobs.");
  205. else console.log(`There are ${activeStatus.length} active jobs.`);
  206. console.table(activeStatus);
  207. break;
  208. }
  209. case "eval": {
  210. const evalCommand = args.join(" ");
  211. console.log(`Running eval command: ${evalCommand}`);
  212. // eslint-disable-next-line no-eval
  213. const response = eval(evalCommand);
  214. console.log(`Eval response: `, response);
  215. break;
  216. }
  217. case "debug": {
  218. // eslint-disable-next-line no-debugger
  219. debugger;
  220. break;
  221. }
  222. case "log": {
  223. const [output, key, action, ...values] = args;
  224. if (
  225. output === undefined ||
  226. key === undefined ||
  227. action === undefined
  228. ) {
  229. console.log(
  230. `Missing required parameters (log <output> <key> <action> [values])`
  231. );
  232. break;
  233. }
  234. let value: any[] | undefined;
  235. if (values !== undefined && values.length >= 1) {
  236. value = values.map(_filter => JSON.parse(_filter));
  237. if (value.length === 1) [value] = value;
  238. }
  239. logBook
  240. // @ts-ignore
  241. .updateOutput(output, key, action, value)
  242. .then(() => console.log("Successfully updated outputs"))
  243. .catch((err: Error) =>
  244. console.log(`Error updating outputs "${err.message}"`)
  245. );
  246. break;
  247. }
  248. default: {
  249. if (!/^\s*$/.test(command))
  250. console.log(`Command "${command}" not found`);
  251. }
  252. }
  253. };
  254. rl.on("line", runCommand);