// ===================================================== // 資料庫關閉管理器 // ===================================================== import { db } from './database'; import { dbFailover } from './database-failover'; import { dbMonitor } from './database-monitor'; import { connectionMonitor } from './connection-monitor'; export class DatabaseShutdownManager { private static instance: DatabaseShutdownManager; private isShuttingDown = false; private shutdownHandlers: (() => Promise)[] = []; private constructor() { this.registerShutdownHandlers(); } public static getInstance(): DatabaseShutdownManager { if (!DatabaseShutdownManager.instance) { DatabaseShutdownManager.instance = new DatabaseShutdownManager(); } return DatabaseShutdownManager.instance; } // 註冊關閉處理器 private registerShutdownHandlers() { // 添加資料庫關閉處理器 this.addShutdownHandler('database', async () => { console.log('🔄 正在關閉主要資料庫連線池...'); try { await db.close(); console.log('✅ 主要資料庫連線池已關閉'); } catch (error) { console.error('❌ 關閉主要資料庫連線池時發生錯誤:', error); } }); // 添加備援資料庫關閉處理器 this.addShutdownHandler('failover', async () => { console.log('🔄 正在關閉備援資料庫連線池...'); try { await dbFailover.close(); console.log('✅ 備援資料庫連線池已關閉'); } catch (error) { console.error('❌ 關閉備援資料庫連線池時發生錯誤:', error); } }); // 添加監控服務關閉處理器 this.addShutdownHandler('monitor', async () => { console.log('🔄 正在停止資料庫監控服務...'); try { dbMonitor.stopMonitoring(); console.log('✅ 資料庫監控服務已停止'); } catch (error) { console.error('❌ 停止資料庫監控服務時發生錯誤:', error); } }); // 添加連線監控關閉處理器 this.addShutdownHandler('connection-monitor', async () => { console.log('🔄 正在停止連線監控服務...'); try { connectionMonitor.stopMonitoring(); console.log('✅ 連線監控服務已停止'); } catch (error) { console.error('❌ 停止連線監控服務時發生錯誤:', error); } }); // 註冊系統信號處理器 this.registerSystemHandlers(); } // 添加關閉處理器 public addShutdownHandler(name: string, handler: () => Promise) { this.shutdownHandlers.push(async () => { try { console.log(`🔄 執行關閉處理器: ${name}`); await handler(); console.log(`✅ 關閉處理器完成: ${name}`); } catch (error) { console.error(`❌ 關閉處理器失敗: ${name}`, error); } }); } // 初始化服務 public initialize(): void { console.log('🚀 初始化資料庫服務...'); // 啟動連線監控 try { connectionMonitor.startMonitoring(30000); // 30秒檢查一次 console.log('✅ 連線監控已啟動'); } catch (error) { console.error('❌ 啟動連線監控失敗:', error); } console.log('✅ 資料庫服務初始化完成'); } // 註冊系統信號處理器 private registerSystemHandlers() { if (typeof process === 'undefined') return; // SIGINT (Ctrl+C) process.on('SIGINT', () => { console.log('\n🛑 收到 SIGINT 信號,開始優雅關閉...'); this.gracefulShutdown(); }); // SIGTERM (終止信號) process.on('SIGTERM', () => { console.log('\n🛑 收到 SIGTERM 信號,開始優雅關閉...'); this.gracefulShutdown(); }); // 未捕獲的異常 process.on('uncaughtException', (error) => { console.error('❌ 未捕獲的異常:', error); this.gracefulShutdown(); }); // 未處理的 Promise 拒絕 process.on('unhandledRejection', (reason, promise) => { console.error('❌ 未處理的 Promise 拒絕:', reason); this.gracefulShutdown(); }); // 程序退出 process.on('exit', () => { if (!this.isShuttingDown) { console.log('🛑 程序即將退出,強制關閉資料庫連線...'); this.forceShutdown(); } }); console.log('✅ 系統信號處理器已註冊'); } // 優雅關閉 public async gracefulShutdown() { if (this.isShuttingDown) { console.log('⚠️ 關閉程序已在進行中,跳過重複請求'); return; } this.isShuttingDown = true; console.log('🔄 開始優雅關閉資料庫連線...'); const startTime = Date.now(); try { // 並行執行所有關閉處理器 await Promise.allSettled( this.shutdownHandlers.map(handler => handler()) ); const duration = Date.now() - startTime; console.log(`✅ 資料庫連線關閉完成,耗時: ${duration}ms`); } catch (error) { console.error('❌ 優雅關閉過程中發生錯誤:', error); } finally { // 強制退出程序 setTimeout(() => { console.log('🛑 強制退出程序'); process.exit(0); }, 5000); // 5秒後強制退出 } } // 強制關閉 public forceShutdown() { console.log('🚨 強制關閉所有資料庫連線...'); // 同步執行關閉處理器(不等待) this.shutdownHandlers.forEach(handler => { try { handler(); } catch (error) { console.error('❌ 強制關閉時發生錯誤:', error); } }); console.log('✅ 強制關閉完成'); } // 獲取關閉狀態 public getShutdownStatus() { return { isShuttingDown: this.isShuttingDown, handlerCount: this.shutdownHandlers.length, registeredHandlers: this.shutdownHandlers.map((_, index) => `handler-${index}`) }; } // 測試關閉機制 public async testShutdown() { console.log('🧪 測試資料庫關閉機制...'); await this.gracefulShutdown(); } } // 導出單例實例 export const dbShutdownManager = DatabaseShutdownManager.getInstance(); // 導出便捷函數 export const gracefulShutdown = () => dbShutdownManager.gracefulShutdown(); export const forceShutdown = () => dbShutdownManager.forceShutdown();