// ===================================================== // 資料庫連接配置 // ===================================================== import mysql from 'mysql2/promise'; // 資料庫配置 const dbConfig = { host: process.env.DB_HOST || 'mysql.theaken.com', port: parseInt(process.env.DB_PORT || '33306'), user: process.env.DB_USER || 'AI_Platform', password: process.env.DB_PASSWORD || 'Aa123456', database: process.env.DB_NAME || 'db_AI_Platform', charset: 'utf8mb4', timezone: '+08:00', acquireTimeout: 60000, timeout: 60000, reconnect: true, connectionLimit: 10, queueLimit: 0, // 添加連接重試和錯誤處理配置 retryDelay: 2000, maxRetries: 3, // 添加連接池配置 idleTimeout: 300000, maxIdle: 10, // 添加 SSL 配置(如果需要) ssl: false, }; // 創建連接池 const pool = mysql.createPool(dbConfig); // 資料庫連接類 export class Database { private static instance: Database; private pool: mysql.Pool; private constructor() { this.pool = pool; } public static getInstance(): Database { if (!Database.instance) { Database.instance = new Database(); } return Database.instance; } // 獲取連接 public async getConnection(): Promise { return await this.pool.getConnection(); } // 執行查詢 public async query(sql: string, params?: any[]): Promise { let connection; let retries = 0; const maxRetries = 3; while (retries < maxRetries) { try { connection = await this.getConnection(); const [rows] = await connection.execute(sql, params); return rows as T[]; } catch (error: any) { console.error(`資料庫查詢錯誤 (嘗試 ${retries + 1}/${maxRetries}):`, error.message); if (connection) { connection.release(); } if (error.code === 'ECONNRESET' || error.code === 'PROTOCOL_CONNECTION_LOST') { retries++; if (retries < maxRetries) { console.log(`等待 ${2000 * retries}ms 後重試...`); await new Promise(resolve => setTimeout(resolve, 2000 * retries)); continue; } } throw error; } finally { if (connection) { connection.release(); } } } throw new Error('資料庫連接失敗,已達到最大重試次數'); } // 執行單一查詢 public async queryOne(sql: string, params?: any[]): Promise { try { const results = await this.query(sql, params); return results.length > 0 ? results[0] : null; } catch (error) { console.error('資料庫單一查詢錯誤:', error); throw error; } } // 執行插入 public async insert(sql: string, params?: any[]): Promise { const connection = await this.getConnection(); try { const [result] = await connection.execute(sql, params); return result as mysql.ResultSetHeader; } finally { connection.release(); } } // 執行更新 public async update(sql: string, params?: any[]): Promise { const connection = await this.getConnection(); try { const [result] = await connection.execute(sql, params); return result as mysql.ResultSetHeader; } finally { connection.release(); } } // 執行刪除 public async delete(sql: string, params?: any[]): Promise { const connection = await this.getConnection(); try { const [result] = await connection.execute(sql, params); return result as mysql.ResultSetHeader; } finally { connection.release(); } } // 開始事務 public async beginTransaction(): Promise { const connection = await this.getConnection(); await connection.beginTransaction(); return connection; } // 提交事務 public async commit(connection: mysql.PoolConnection): Promise { await connection.commit(); connection.release(); } // 回滾事務 public async rollback(connection: mysql.PoolConnection): Promise { await connection.rollback(); connection.release(); } // 關閉連接池 public async close(): Promise { await this.pool.end(); } } // 導出單例實例 export const db = Database.getInstance(); // 導出類型 export type { PoolConnection } from 'mysql2/promise';