server-connector.class.ts 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. import axios, { AxiosError } from 'axios';
  2. import moment from 'moment';
  3. import { Pool } from 'mysql';
  4. import defaults from '../../../common/defaults.module';
  5. import { Logger } from '../../../common/util/logger.class';
  6. import { FCMController } from './fcm-controller.class';
  7. import { Timer } from '../timer.class';
  8. import { MariaDBDatabase } from './mariadb-database.class';
  9. export class ServerConnector {
  10. private subscriptions: Array<{ id: number; interval: number; server: Server }> = [];
  11. private db!: MariaDBDatabase;
  12. constructor(pool: Pool) {
  13. this.db = new MariaDBDatabase(pool);
  14. (async () => {
  15. try {
  16. await this.db.open();
  17. const serverList = await this.db.getAllServerConfigs();
  18. for (const server of serverList) {
  19. let interval = Number(server.config['syncInterval']);
  20. if (Number.isNaN(interval)) interval = defaults.serverSync.interval;
  21. Logger.info('[INFO] Starting Server Sync Connector for', server.title, 'with interval', interval, 'seconds ...');
  22. const id = Timer.instance.subscribe(interval, async () => await this.timerTick(server));
  23. this.subscriptions.push({ id, interval, server });
  24. Logger.info('[INFO] Initial Sync for', server.title, '...');
  25. await this.timerTick(server);
  26. }
  27. } catch (err) {
  28. Logger.error('[FATAL] Initializing ServerConnector failed:', err);
  29. Logger.error('[EXITING]');
  30. process.exit(1);
  31. }
  32. })();
  33. }
  34. private async timerTick(server: Server & { errors?: number }) {
  35. Logger.debug('[DEBUG] TICK', new Date(), JSON.stringify(server));
  36. if (process.env.DEV_MODE) return Logger.warn('[WARN] DEV_MODE active - sync inactive.');
  37. let trxHdl: number | undefined = undefined;
  38. try {
  39. // Start Transaction, receiving Data and a Transaction Handle
  40. let response = await axios.get(`http://${server.fqdn}:8890/`, { responseType: 'json' });
  41. trxHdl = response.data.hdl;
  42. if (!trxHdl) return; // No data
  43. const data: ReducedData[] = response.data.data.map((entry: any) => ({ ...entry, time: new Date(entry.time) }));
  44. // Process data in DB
  45. await this.db.insertServerData(server.id, data);
  46. // Commit Transaction
  47. await axios.patch(`http://${server.fqdn}:8890/${trxHdl}`, null, { responseType: 'json' });
  48. if (server.errors) {
  49. // notify [RECOVERY]
  50. try {
  51. await FCMController.instance.sendNotificationToTopic(defaults.fcmTopics.serverData, {
  52. title: `[RECOVERY] ${moment().format('HH:mm')} Server '${server.title}': [OK]`,
  53. body: `[RECOVERY] Server '${server.title}': daemon OK`
  54. });
  55. } catch (err) {
  56. Logger.error('[ERROR] Notification failure:', err);
  57. }
  58. }
  59. server.errors = 0;
  60. } catch (err) {
  61. Logger.error('[ERROR] Server data sync failed:', err);
  62. if (err instanceof AxiosError) {
  63. if (['ECONNREFUSED', 'ECONNABORTED'].includes(err.code ?? '')) {
  64. try {
  65. server.errors = (server.errors ?? 0) + 1;
  66. await FCMController.instance.sendNotificationToTopic(defaults.fcmTopics.serverData, {
  67. title: `[WARN] ${moment().format('HH:mm')} Server '${server.title}': daemon unreachable (${err.code})`,
  68. body: new String(err).toString()
  69. });
  70. } catch (err) {
  71. Logger.error('[ERROR] Notification failure:', err);
  72. }
  73. }
  74. }
  75. if (!!trxHdl) {
  76. Logger.error(`[WARN] Rolling back transaction #${trxHdl} ... `);
  77. const response = await axios.delete(`http://${server.fqdn}:8890/${trxHdl}`, { responseType: 'json' });
  78. if (response.data.ok) {
  79. Logger.error(`[WARN] Rollback succeeded.`);
  80. }
  81. }
  82. // if (!!db) await db.close();
  83. }
  84. }
  85. async close() {
  86. if (!this.db) return;
  87. await this.db.close();
  88. }
  89. }