feat: 迁移自定义功能至 1.5.9.9 版本
包含音乐源限制、CI 防 OOM 优化、数据库连接池优化、管理端权限及 UI 细节定制等功能
This commit is contained in:
@@ -1,10 +1,5 @@
|
||||
import { db, getConnectionStatus } from '~/drizzle/db'
|
||||
import { sql } from 'drizzle-orm'
|
||||
import {
|
||||
getConnectionPoolStatus,
|
||||
getDatabaseMetrics
|
||||
} from './database-health'
|
||||
import { getServerTimestamp } from './serverTime'
|
||||
|
||||
/**
|
||||
* 数据库管理器
|
||||
@@ -33,7 +28,7 @@ export class DatabaseManager {
|
||||
connectionStatus: string
|
||||
error?: string
|
||||
}> {
|
||||
const now = getServerTimestamp()
|
||||
const now = Date.now()
|
||||
|
||||
// 检查缓存
|
||||
if (this.healthCheckCache && now - this.healthCheckCache.timestamp < this.CACHE_TTL) {
|
||||
@@ -111,13 +106,12 @@ export class DatabaseManager {
|
||||
WHERE datname = current_database() AND state = 'active'
|
||||
`)
|
||||
|
||||
const sizeRow = sizeResult[0] as { database_size?: string } | undefined
|
||||
const connectionRow = connectionStats[0] as { active_connections?: number | string } | undefined
|
||||
const sizeRow = sizeResult[0] as any
|
||||
const connectionRow = connectionStats[0] as any
|
||||
|
||||
return {
|
||||
databaseSize: sizeRow?.database_size || 'Unknown',
|
||||
activeConnections:
|
||||
Number.parseInt(String(connectionRow?.active_connections ?? '0'), 10) || 0,
|
||||
activeConnections: parseInt(connectionRow?.active_connections) || 0,
|
||||
serverless: true // Neon Database 是无服务器架构
|
||||
}
|
||||
} catch (error) {
|
||||
@@ -132,69 +126,35 @@ export class DatabaseManager {
|
||||
* 获取连接状态 - 适配 Neon Database 无服务器架构
|
||||
*/
|
||||
async getConnectionStatus(): Promise<{
|
||||
connected: boolean
|
||||
status: string
|
||||
activeConnections: number
|
||||
serverlessMode: boolean
|
||||
autoSuspend: boolean
|
||||
error: string | null
|
||||
}> {
|
||||
try {
|
||||
const connectionStatus = await getConnectionStatus()
|
||||
|
||||
// 用最小查询判断真实连通性,避免底层连接对象状态或统计查询误判。
|
||||
await db.execute(sql`SELECT 1 as connection_check`)
|
||||
|
||||
// 获取当前活跃连接数
|
||||
let activeConnections = 0
|
||||
try {
|
||||
const connectionStats = await db.execute(sql`
|
||||
SELECT count(*) as active_connections
|
||||
FROM pg_stat_activity
|
||||
WHERE datname = current_database() AND state = 'active'
|
||||
`)
|
||||
const connectionStats = await db.execute(sql`
|
||||
SELECT count(*) as active_connections
|
||||
FROM pg_stat_activity
|
||||
WHERE datname = current_database() AND state = 'active'
|
||||
`)
|
||||
|
||||
const connRow = connectionStats[0] as { active_connections?: number | string } | undefined
|
||||
activeConnections = Number.parseInt(String(connRow?.active_connections ?? '0'), 10) || 0
|
||||
} catch (metricsError) {
|
||||
console.warn('Failed to get active connection count:', metricsError)
|
||||
}
|
||||
const connRow = connectionStats[0] as any
|
||||
|
||||
return {
|
||||
connected: true,
|
||||
status: connectionStatus.status || 'connected',
|
||||
activeConnections,
|
||||
status: connectionStatus.status,
|
||||
activeConnections: parseInt(connRow?.active_connections) || 0,
|
||||
serverlessMode: true, // Neon Database 是无服务器架构
|
||||
autoSuspend: true, // 支持自动暂停
|
||||
error: null
|
||||
autoSuspend: true // 支持自动暂停
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Failed to get connection status:', error)
|
||||
return {
|
||||
connected: false,
|
||||
status: 'error',
|
||||
activeConnections: 0,
|
||||
serverlessMode: true,
|
||||
autoSuspend: true,
|
||||
error: error instanceof Error ? error.message : 'Failed to retrieve connection status'
|
||||
}
|
||||
throw new Error('Failed to retrieve connection status')
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取连接池状态
|
||||
*/
|
||||
async getConnectionPoolStatus() {
|
||||
return await getConnectionPoolStatus()
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取数据库性能指标
|
||||
*/
|
||||
async getPerformanceMetrics() {
|
||||
return await getDatabaseMetrics()
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量清理过期会话
|
||||
*/
|
||||
@@ -206,8 +166,7 @@ export class DatabaseManager {
|
||||
`)
|
||||
|
||||
// postgres-js returns count in the result array object properties
|
||||
const deleteResult = result as { count?: number | string }
|
||||
return Number.parseInt(String(deleteResult.count ?? '0'), 10) || 0
|
||||
return (result as any).count || 0
|
||||
} catch (error) {
|
||||
console.error('Failed to cleanup expired sessions:', error)
|
||||
throw new Error('Failed to cleanup expired sessions')
|
||||
|
||||
Reference in New Issue
Block a user