Files
ai-showcase-platform/lib/database-middleware.ts

160 lines
4.4 KiB
TypeScript

// =====================================================
// 資料庫連線管理中間件
// =====================================================
import { NextRequest, NextResponse } from 'next/server';
import { db } from './database';
import { dbMonitor } from './database-monitor';
import { dbShutdownManager } from './database-shutdown-manager';
// 連線池狀態追蹤
let connectionCount = 0;
const maxConnections = 3; // 與資料庫配置保持一致
export function withDatabaseConnection<T extends any[]>(
handler: (...args: T) => Promise<NextResponse>
) {
return async (...args: T): Promise<NextResponse> => {
// 檢查連線池狀態
if (connectionCount >= maxConnections) {
console.warn(`⚠️ 連線池已滿 (${connectionCount}/${maxConnections}),等待可用連線...`);
// 等待一段時間後重試
await new Promise(resolve => setTimeout(resolve, 100));
if (connectionCount >= maxConnections) {
return NextResponse.json(
{
success: false,
error: '資料庫連線池已滿,請稍後再試',
retryAfter: 5 // 建議5秒後重試
},
{ status: 503 }
);
}
}
connectionCount++;
try {
const result = await handler(...args);
return result;
} catch (error) {
console.error('資料庫操作錯誤:', error);
// 根據錯誤類型返回適當的響應
if (error instanceof Error) {
if (error.message.includes('ER_CON_COUNT_ERROR')) {
return NextResponse.json(
{
success: false,
error: '資料庫連線數已達上限,請稍後再試',
retryAfter: 10
},
{ status: 503 }
);
} else if (error.message.includes('ECONNRESET') || error.message.includes('PROTOCOL_CONNECTION_LOST')) {
return NextResponse.json(
{
success: false,
error: '資料庫連線中斷,請重試',
retryAfter: 3
},
{ status: 503 }
);
}
}
return NextResponse.json(
{
success: false,
error: '資料庫操作失敗',
details: error instanceof Error ? error.message : '未知錯誤'
},
{ status: 500 }
);
} finally {
connectionCount--;
}
};
}
// 連線池健康檢查
export async function checkConnectionHealth(): Promise<{
isHealthy: boolean;
connectionCount: number;
maxConnections: number;
usagePercentage: number;
}> {
try {
const stats = dbMonitor.getConnectionStats();
return {
isHealthy: stats.usagePercentage < 80,
connectionCount: stats.currentConnections,
maxConnections: stats.maxConnections,
usagePercentage: stats.usagePercentage
};
} catch (error) {
console.error('連線健康檢查失敗:', error);
return {
isHealthy: false,
connectionCount: 0,
maxConnections: 0,
usagePercentage: 100
};
}
}
// 自動釋放空閒連線
export async function autoReleaseIdleConnections(): Promise<boolean> {
try {
const health = await checkConnectionHealth();
if (health.usagePercentage > 70) {
console.log('🔄 連線使用率過高,嘗試釋放空閒連線...');
return await dbMonitor.releaseIdleConnections();
}
return true;
} catch (error) {
console.error('自動釋放連線失敗:', error);
return false;
}
}
// 連線池監控
export function startConnectionMonitoring() {
// 每30秒檢查一次連線狀態
dbMonitor.startMonitoring(30000);
// 每5分鐘嘗試釋放空閒連線
setInterval(async () => {
await autoReleaseIdleConnections();
}, 5 * 60 * 1000);
console.log('🔍 資料庫連線監控已啟動');
}
// 優雅的關閉(使用新的關閉管理器)
export async function gracefulShutdown() {
console.log('🔄 使用資料庫關閉管理器進行優雅關閉...');
await dbShutdownManager.gracefulShutdown();
}
// 強制關閉
export function forceShutdown() {
console.log('🚨 強制關閉資料庫連線...');
dbShutdownManager.forceShutdown();
}
// 獲取關閉狀態
export function getShutdownStatus() {
return dbShutdownManager.getShutdownStatus();
}
// 測試關閉機制
export async function testShutdown() {
return await dbShutdownManager.testShutdown();
}