Explorar o código

Server: Graceful exit on SIGTERM (system unit'S default KillSignal)

Christian Kahlau %!s(int64=3) %!d(string=hai) anos
pai
achega
fd73cb807f

+ 2 - 0
server/src/ctrl/database.class.ts

@@ -43,6 +43,8 @@ export class Database extends SQLiteController {
       });
       Logger.info('[INFO]', exists ? 'Opened' : 'Created', 'SQLite3 Database file', DATA_FILE);
 
+      if (!this.db) throw new Error('Database not opened.');
+
       if (!exists) {
         // INITIAL TABLE SETUP
         await this.run(

+ 7 - 3
server/src/ctrl/sqlite-controller.base.ts

@@ -1,7 +1,7 @@
 import { Database, RunResult, Statement } from 'sqlite3';
 
 export abstract class SQLiteController {
-  protected db!: Database;
+  protected db?: Database;
 
   public run(sql: string, params: any): Promise<RunResult> {
     return new Promise<RunResult>((res, rej) => {
@@ -31,6 +31,7 @@ export abstract class SQLiteController {
   public prepare(sql: string) {
     return new Promise<Statement>((res, rej) => {
       try {
+        if (!this.db) return rej(new Error('Database not opened.'));
         this.db.prepare(sql, function (err) {
           if (err) return rej(err);
           res(this);
@@ -61,7 +62,10 @@ export abstract class SQLiteController {
   }
 
   async close() {
-    if (!this.db) return;
-    await new Promise<void>((res, rej) => this.db.close(err => (err ? rej(err) : res())));
+    await new Promise<void>((res, rej) => {
+      if (!this.db) return res();
+      this.db.close(err => (err ? rej(err) : res()));
+    });
+    this.db = undefined;
   }
 }

+ 26 - 1
server/src/index.ts

@@ -14,11 +14,16 @@ dotenv.config();
 const LOG_LEVEL: LogLevel = (process.env.LOG_LEVEL as LogLevel) || 'INFO';
 Logger.logLevel = LOG_LEVEL;
 
+process.on('SIGABRT', exitGracefully);
+process.on('SIGQUIT', exitGracefully);
+process.on('SIGTERM', exitGracefully);
+
+let pool: ControllerPool;
 (async () => {
   const db = new Database();
   await db.open(true);
 
-  const pool: ControllerPool = {
+  pool = {
     db,
     serverConnector: new ServerConnector(),
     httpChecks: new HttpCheckController()
@@ -27,3 +32,23 @@ Logger.logLevel = LOG_LEVEL;
   Timer.instance.start();
   new Webserver(Number(process.env.WEB_PORT ?? '80'), pool);
 })();
+
+async function exitGracefully(...args: any[]) {
+  Logger.info(`[EXITING] Graceful exit, received ${JSON.stringify(args)}`);
+  if (pool) {
+    try {
+      Logger.info(`[EXITING] Tear down ServerConnector ...`);
+      await pool.serverConnector.close();
+
+      Logger.info(`[EXITING] Tear down HttpCheckController ...`);
+      await pool.httpChecks.close();
+
+      Logger.info(`[EXITING] Tear down Main Database Controller ...`);
+      await pool.serverConnector.close();
+    } catch (err) {
+      Logger.error(`[ERROR] Tear down sequence failed:`, err);
+      process.exit(2);
+    }
+  }
+  process.exit(0);
+}