修復 too many connection 問題

This commit is contained in:
2025-09-21 02:46:16 +08:00
parent a36ab3c98d
commit 808d5bb52c
36 changed files with 5582 additions and 249 deletions

View File

@@ -0,0 +1,37 @@
// =====================================================
// 獲取競賽詳情 API
// =====================================================
import { NextRequest, NextResponse } from 'next/server';
import { CompetitionService } from '@/lib/services/database-service';
export async function GET(request: NextRequest, { params }: { params: { id: string } }) {
try {
const { id } = await params;
// 獲取競賽詳情
const competition = await CompetitionService.getCompetitionById(id);
if (!competition) {
return NextResponse.json({
success: false,
message: '競賽不存在',
error: '找不到指定的競賽'
}, { status: 404 });
}
return NextResponse.json({
success: true,
message: '競賽詳情獲取成功',
data: competition
});
} catch (error) {
console.error('獲取競賽詳情失敗:', error);
return NextResponse.json({
success: false,
message: '獲取競賽詳情失敗',
error: error instanceof Error ? error.message : '未知錯誤'
}, { status: 500 });
}
}

View File

@@ -0,0 +1,122 @@
// =====================================================
// 連線監控 API
// =====================================================
import { NextRequest, NextResponse } from 'next/server';
import { smartPool } from '@/lib/smart-connection-pool';
export async function GET(request: NextRequest) {
try {
const { searchParams } = new URL(request.url);
const action = searchParams.get('action') || 'stats';
switch (action) {
case 'stats':
// 獲取連線統計
const stats = smartPool.getConnectionStats();
return NextResponse.json({
success: true,
message: '連線統計獲取成功',
data: stats
});
case 'cleanup':
// 強制清理連線
console.log('🧹 執行強制連線清理...');
smartPool.forceCleanup();
const newStats = smartPool.getConnectionStats();
return NextResponse.json({
success: true,
message: '連線清理完成',
data: newStats
});
case 'test':
// 測試智能連線
try {
const testResult = await smartPool.executeQueryOne(
'SELECT 1 as test_value',
[],
{ userId: 'test', sessionId: 'test-session', requestId: 'test-request' }
);
return NextResponse.json({
success: true,
message: '智能連線測試成功',
data: {
testResult,
stats: smartPool.getConnectionStats()
}
});
} catch (error) {
return NextResponse.json({
success: false,
error: '智能連線測試失敗',
details: error instanceof Error ? error.message : '未知錯誤'
}, { status: 500 });
}
default:
return NextResponse.json({
success: false,
error: '無效的操作參數',
availableActions: ['stats', 'cleanup', 'test']
}, { status: 400 });
}
} catch (error) {
console.error('❌ 連線監控 API 錯誤:', error);
return NextResponse.json({
success: false,
error: 'API 請求失敗',
details: error instanceof Error ? error.message : '未知錯誤'
}, { status: 500 });
}
}
export async function POST(request: NextRequest) {
try {
const body = await request.json();
const { action, maxIdleTime, maxConnectionAge } = body;
switch (action) {
case 'config':
// 更新清理配置
smartPool.setCleanupParams(maxIdleTime, maxConnectionAge);
return NextResponse.json({
success: true,
message: '清理配置更新成功',
data: {
maxIdleTime: maxIdleTime || '未變更',
maxConnectionAge: maxConnectionAge || '未變更'
}
});
case 'cleanup':
// 強制清理連線
console.log('🧹 執行強制連線清理...');
smartPool.forceCleanup();
const stats = smartPool.getConnectionStats();
return NextResponse.json({
success: true,
message: '連線清理完成',
data: stats
});
default:
return NextResponse.json({
success: false,
error: '無效的操作參數',
availableActions: ['config', 'cleanup']
}, { status: 400 });
}
} catch (error) {
console.error('❌ 連線監控 POST API 錯誤:', error);
return NextResponse.json({
success: false,
error: 'API 請求失敗',
details: error instanceof Error ? error.message : '未知錯誤'
}, { status: 500 });
}
}

59
app/api/debug-ip/route.ts Normal file
View File

@@ -0,0 +1,59 @@
// =====================================================
// IP 調試 API
// =====================================================
import { NextRequest, NextResponse } from 'next/server';
import { smartIPDetector } from '@/lib/smart-ip-detector';
export async function GET(request: NextRequest) {
try {
// 使用智能 IP 偵測器
const ipDetection = smartIPDetector.detectClientIP(request);
// 收集所有可能的 IP 信息
const ipInfo = {
// 智能偵測結果
smartDetection: ipDetection,
// 請求標頭
headers: {
'x-forwarded-for': request.headers.get('x-forwarded-for'),
'x-real-ip': request.headers.get('x-real-ip'),
'cf-connecting-ip': request.headers.get('cf-connecting-ip'),
'x-client-ip': request.headers.get('x-client-ip'),
'x-forwarded': request.headers.get('x-forwarded'),
'x-cluster-client-ip': request.headers.get('x-cluster-client-ip'),
'x-original-forwarded-for': request.headers.get('x-original-forwarded-for'),
'x-remote-addr': request.headers.get('x-remote-addr'),
'remote-addr': request.headers.get('remote-addr'),
'client-ip': request.headers.get('client-ip'),
'user-agent': request.headers.get('user-agent'),
'host': request.headers.get('host'),
},
// NextRequest 的 IP
nextRequestIP: request.ip,
// 環境變數
env: {
NODE_ENV: process.env.NODE_ENV,
VERCEL: process.env.VERCEL,
VERCEL_REGION: process.env.VERCEL_REGION,
},
// 所有標頭(用於調試)
allHeaders: Object.fromEntries(request.headers.entries()),
};
return NextResponse.json({
success: true,
message: 'IP 調試信息獲取成功',
data: ipInfo,
timestamp: new Date().toISOString()
});
} catch (error) {
console.error('❌ IP 調試 API 錯誤:', error);
return NextResponse.json({
success: false,
error: 'IP 調試失敗',
details: error instanceof Error ? error.message : '未知錯誤'
}, { status: 500 });
}
}

View File

@@ -0,0 +1,104 @@
// =====================================================
// 緊急連線清理 API
// =====================================================
import { NextRequest, NextResponse } from 'next/server';
import { emergencyCleanup } from '@/lib/emergency-connection-cleanup';
export async function POST(request: NextRequest) {
try {
const body = await request.json();
const { action } = body;
switch (action) {
case 'cleanup':
// 執行緊急清理
console.log('🚨 收到緊急清理請求');
await emergencyCleanup.emergencyCleanup();
return NextResponse.json({
success: true,
message: '緊急清理完成',
timestamp: new Date().toISOString()
});
case 'kill-all':
// 強制殺死所有連線
console.log('💀 收到強制殺死連線請求');
await emergencyCleanup.forceKillAllConnections();
return NextResponse.json({
success: true,
message: '強制殺死連線完成',
timestamp: new Date().toISOString()
});
case 'details':
// 獲取連線詳情
const connections = await emergencyCleanup.getConnectionDetails();
return NextResponse.json({
success: true,
message: '連線詳情獲取成功',
data: {
connectionCount: connections.length,
connections: connections
},
timestamp: new Date().toISOString()
});
default:
return NextResponse.json({
success: false,
error: '無效的操作參數',
availableActions: ['cleanup', 'kill-all', 'details']
}, { status: 400 });
}
} catch (error) {
console.error('❌ 緊急清理 API 錯誤:', error);
return NextResponse.json({
success: false,
error: '緊急清理失敗',
details: error instanceof Error ? error.message : '未知錯誤'
}, { status: 500 });
}
}
export async function GET(request: NextRequest) {
try {
const { searchParams } = new URL(request.url);
const action = searchParams.get('action') || 'details';
switch (action) {
case 'details':
// 獲取連線詳情
const connections = await emergencyCleanup.getConnectionDetails();
return NextResponse.json({
success: true,
message: '連線詳情獲取成功',
data: {
connectionCount: connections.length,
connections: connections
},
timestamp: new Date().toISOString()
});
default:
return NextResponse.json({
success: false,
error: '無效的操作參數',
availableActions: ['details']
}, { status: 400 });
}
} catch (error) {
console.error('❌ 緊急清理 GET API 錯誤:', error);
return NextResponse.json({
success: false,
error: '獲取連線詳情失敗',
details: error instanceof Error ? error.message : '未知錯誤'
}, { status: 500 });
}
}

177
app/api/ip-cleanup/route.ts Normal file
View File

@@ -0,0 +1,177 @@
// =====================================================
// 基於 IP 的連線清理 API
// =====================================================
import { NextRequest, NextResponse } from 'next/server';
import { smartIPPool } from '@/lib/smart-ip-connection-pool';
import { smartIPDetector } from '@/lib/smart-ip-detector';
export async function POST(request: NextRequest) {
try {
const body = await request.json();
const { action, targetIP } = body;
// 使用智能 IP 偵測器
const ipDetection = smartIPDetector.detectClientIP(request);
const clientIP = ipDetection.detectedIP;
console.log('🎯 智能 IP 偵測結果:', {
detectedIP: clientIP,
confidence: ipDetection.confidence,
source: ipDetection.source,
isPublicIP: ipDetection.isPublicIP,
allCandidates: ipDetection.allCandidates
});
// 設置客戶端 IP
smartIPPool.setClientIP(clientIP);
switch (action) {
case 'cleanup-current':
// 清理當前 IP 的連線
console.log(`🧹 收到清理當前 IP 連線請求: ${clientIP}`);
const cleanupResult = await smartIPPool.cleanupCurrentIPConnections();
return NextResponse.json({
success: cleanupResult.success,
message: cleanupResult.message,
data: {
clientIP,
killedCount: cleanupResult.killedCount
},
timestamp: new Date().toISOString()
});
case 'cleanup-specific':
// 清理指定 IP 的連線
if (!targetIP) {
return NextResponse.json({
success: false,
error: '缺少目標 IP 參數'
}, { status: 400 });
}
console.log(`🧹 收到清理指定 IP 連線請求: ${targetIP}`);
const specificCleanupResult = await smartIPPool.cleanupIPConnections(targetIP);
return NextResponse.json({
success: specificCleanupResult.success,
message: specificCleanupResult.message,
data: {
targetIP,
killedCount: specificCleanupResult.killedCount
},
timestamp: new Date().toISOString()
});
case 'cleanup-local':
// 清理本地追蹤的連線
console.log('🧹 收到清理本地連線請求');
const localCleanupCount = smartIPPool.cleanupLocalConnections();
return NextResponse.json({
success: true,
message: `已清理 ${localCleanupCount} 個本地追蹤的連線`,
data: {
clientIP,
cleanedCount: localCleanupCount
},
timestamp: new Date().toISOString()
});
default:
return NextResponse.json({
success: false,
error: '無效的操作參數',
availableActions: ['cleanup-current', 'cleanup-specific', 'cleanup-local']
}, { status: 400 });
}
} catch (error) {
console.error('❌ IP 清理 API 錯誤:', error);
return NextResponse.json({
success: false,
error: 'IP 清理失敗',
details: error instanceof Error ? error.message : '未知錯誤'
}, { status: 500 });
}
}
export async function GET(request: NextRequest) {
try {
const { searchParams } = new URL(request.url);
const action = searchParams.get('action') || 'status';
const targetIP = searchParams.get('ip');
// 使用智能 IP 偵測器
const ipDetection = smartIPDetector.detectClientIP(request);
const clientIP = ipDetection.detectedIP;
// 設置客戶端 IP
smartIPPool.setClientIP(clientIP);
switch (action) {
case 'status':
// 獲取當前 IP 的連線狀態
const currentIPStatus = await smartIPPool.getCurrentIPConnections();
return NextResponse.json({
success: true,
message: '連線狀態獲取成功',
data: {
detectedIP: clientIP,
...currentIPStatus
},
timestamp: new Date().toISOString()
});
case 'status-specific':
// 獲取指定 IP 的連線狀態
if (!targetIP) {
return NextResponse.json({
success: false,
error: '缺少目標 IP 參數'
}, { status: 400 });
}
const specificIPStatus = await smartIPPool.getIPConnections(targetIP);
return NextResponse.json({
success: true,
message: '指定 IP 連線狀態獲取成功',
data: {
targetIP,
...specificIPStatus
},
timestamp: new Date().toISOString()
});
case 'local-stats':
// 獲取本地連線統計
const localStats = smartIPPool.getLocalConnectionStats();
return NextResponse.json({
success: true,
message: '本地連線統計獲取成功',
data: {
detectedIP: clientIP,
...localStats
},
timestamp: new Date().toISOString()
});
default:
return NextResponse.json({
success: false,
error: '無效的操作參數',
availableActions: ['status', 'status-specific', 'local-stats']
}, { status: 400 });
}
} catch (error) {
console.error('❌ IP 清理 GET API 錯誤:', error);
return NextResponse.json({
success: false,
error: '獲取連線狀態失敗',
details: error instanceof Error ? error.message : '未知錯誤'
}, { status: 500 });
}
}

View File

@@ -0,0 +1,78 @@
// =====================================================
// 手動設置客戶端 IP API
// =====================================================
import { NextRequest, NextResponse } from 'next/server';
import { smartIPPool } from '@/lib/smart-ip-connection-pool';
export async function POST(request: NextRequest) {
try {
const body = await request.json();
const { clientIP } = body;
if (!clientIP) {
return NextResponse.json({
success: false,
error: '缺少客戶端 IP 參數'
}, { status: 400 });
}
console.log('🔧 手動設置客戶端 IP:', clientIP);
// 設置客戶端 IP
smartIPPool.setClientIP(clientIP);
return NextResponse.json({
success: true,
message: `客戶端 IP 已設置為: ${clientIP}`,
data: {
clientIP,
timestamp: new Date().toISOString()
}
});
} catch (error) {
console.error('❌ 設置客戶端 IP 失敗:', error);
return NextResponse.json({
success: false,
error: '設置客戶端 IP 失敗',
details: error instanceof Error ? error.message : '未知錯誤'
}, { status: 500 });
}
}
export async function GET(request: NextRequest) {
try {
const { searchParams } = new URL(request.url);
const clientIP = searchParams.get('ip');
if (!clientIP) {
return NextResponse.json({
success: false,
error: '缺少 IP 參數'
}, { status: 400 });
}
console.log('🔧 通過 GET 設置客戶端 IP:', clientIP);
// 設置客戶端 IP
smartIPPool.setClientIP(clientIP);
return NextResponse.json({
success: true,
message: `客戶端 IP 已設置為: ${clientIP}`,
data: {
clientIP,
timestamp: new Date().toISOString()
}
});
} catch (error) {
console.error('❌ 設置客戶端 IP 失敗:', error);
return NextResponse.json({
success: false,
error: '設置客戶端 IP 失敗',
details: error instanceof Error ? error.message : '未知錯誤'
}, { status: 500 });
}
}

View File

@@ -0,0 +1,100 @@
// =====================================================
// 測試資料庫關閉機制 API
// =====================================================
import { NextRequest, NextResponse } from 'next/server';
import { dbShutdownManager } from '@/lib/database-shutdown-manager';
export async function GET(request: NextRequest) {
try {
const { searchParams } = new URL(request.url);
const action = searchParams.get('action') || 'status';
switch (action) {
case 'status':
// 獲取關閉狀態
const status = dbShutdownManager.getShutdownStatus();
return NextResponse.json({
success: true,
message: '關閉狀態查詢成功',
data: status
});
case 'test':
// 測試關閉機制(不會真的關閉)
console.log('🧪 測試關閉機制...');
const testStatus = dbShutdownManager.getShutdownStatus();
return NextResponse.json({
success: true,
message: '關閉機制測試成功',
data: {
...testStatus,
testTime: new Date().toISOString()
}
});
case 'force':
// 強制關閉(僅用於測試)
console.log('🚨 執行強制關閉測試...');
dbShutdownManager.forceShutdown();
return NextResponse.json({
success: true,
message: '強制關閉測試完成',
data: {
timestamp: new Date().toISOString()
}
});
default:
return NextResponse.json({
success: false,
error: '無效的操作參數',
availableActions: ['status', 'test', 'force']
}, { status: 400 });
}
} catch (error) {
console.error('❌ 測試關閉機制時發生錯誤:', error);
return NextResponse.json({
success: false,
error: '測試失敗',
details: error instanceof Error ? error.message : '未知錯誤'
}, { status: 500 });
}
}
export async function POST(request: NextRequest) {
try {
const body = await request.json();
const { action } = body;
switch (action) {
case 'graceful':
// 優雅關閉(僅用於測試)
console.log('🔄 執行優雅關閉測試...');
await dbShutdownManager.gracefulShutdown();
return NextResponse.json({
success: true,
message: '優雅關閉測試完成',
data: {
timestamp: new Date().toISOString()
}
});
default:
return NextResponse.json({
success: false,
error: '無效的操作參數',
availableActions: ['graceful']
}, { status: 400 });
}
} catch (error) {
console.error('❌ 執行關閉測試時發生錯誤:', error);
return NextResponse.json({
success: false,
error: '關閉測試失敗',
details: error instanceof Error ? error.message : '未知錯誤'
}, { status: 500 });
}
}

View File

@@ -0,0 +1,96 @@
// =====================================================
// 終極連線清理 API
// =====================================================
import { NextRequest, NextResponse } from 'next/server';
import { ultimateKiller } from '@/lib/ultimate-connection-killer';
export async function POST(request: NextRequest) {
try {
const body = await request.json();
const { action } = body;
switch (action) {
case 'kill-all':
// 終極清理 - 殺死所有連線
console.log('💀 收到終極清理請求');
const killResult = await ultimateKiller.ultimateKill();
return NextResponse.json({
success: killResult.success,
message: killResult.message || '終極清理完成',
data: killResult,
timestamp: new Date().toISOString()
});
case 'restart':
// 強制重啟資料庫連線
console.log('🔄 收到強制重啟請求');
const restartResult = await ultimateKiller.forceRestart();
return NextResponse.json({
success: restartResult.success,
message: restartResult.message || '強制重啟完成',
data: restartResult,
timestamp: new Date().toISOString()
});
default:
return NextResponse.json({
success: false,
error: '無效的操作參數',
availableActions: ['kill-all', 'restart']
}, { status: 400 });
}
} catch (error) {
console.error('❌ 終極清理 API 錯誤:', error);
return NextResponse.json({
success: false,
error: '終極清理失敗',
details: error instanceof Error ? error.message : '未知錯誤'
}, { status: 500 });
}
}
export async function GET(request: NextRequest) {
try {
const { searchParams } = new URL(request.url);
const action = searchParams.get('action') || 'status';
switch (action) {
case 'status':
// 檢查連線狀態
const status = await ultimateKiller.checkStatus();
if (status) {
return NextResponse.json({
success: true,
message: '連線狀態獲取成功',
data: status,
timestamp: new Date().toISOString()
});
} else {
return NextResponse.json({
success: false,
error: '無法獲取連線狀態'
}, { status: 500 });
}
default:
return NextResponse.json({
success: false,
error: '無效的操作參數',
availableActions: ['status']
}, { status: 400 });
}
} catch (error) {
console.error('❌ 終極清理 GET API 錯誤:', error);
return NextResponse.json({
success: false,
error: '獲取連線狀態失敗',
details: error instanceof Error ? error.message : '未知錯誤'
}, { status: 500 });
}
}