新增:Markdown编辑器/数据库优化/安全修复
- Markdown 编辑器:实时预览、PDF 导出、独立查看器 - 数据库优化:动态连接池、查询缓存、Redis Pipeline - 窗口置顶功能 - 文件系统增强:右键菜单、编辑器集成、收藏夹重构 - 安全修复:XSS 防护、路径穿越、HTML 注入 - 代码质量:正则预编译、缓存锁优化、死代码清理
This commit is contained in:
@@ -5,6 +5,7 @@ import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"u-desk/internal/common"
|
||||
"u-desk/internal/crypto"
|
||||
@@ -18,7 +19,10 @@ type ConnectionPool struct {
|
||||
mongoClients map[uint]*MongoClient
|
||||
|
||||
// 新增:MySQL 真连接池
|
||||
mysqlPool *MySQLConnectionPool
|
||||
mysqlPool *MySQLConnectionPool
|
||||
|
||||
// 查询优化器
|
||||
queryOptimizer *QueryOptimizer
|
||||
|
||||
mu sync.RWMutex
|
||||
}
|
||||
@@ -38,18 +42,37 @@ func GetPool() *ConnectionPool {
|
||||
// 启动维护协程
|
||||
mysqlPool.StartMaintenance()
|
||||
|
||||
// 创建查询优化器
|
||||
queryOptimizer := NewQueryOptimizer(nil)
|
||||
|
||||
globalPool = &ConnectionPool{
|
||||
mysqlClients: make(map[uint]*MySQLClient),
|
||||
redisClients: make(map[uint]*RedisClient),
|
||||
mongoClients: make(map[uint]*MongoClient),
|
||||
mysqlPool: mysqlPool,
|
||||
mysqlPool: mysqlPool,
|
||||
queryOptimizer: queryOptimizer,
|
||||
}
|
||||
})
|
||||
return globalPool
|
||||
}
|
||||
|
||||
// PooledClient 带释放语义的客户端包装
|
||||
type PooledClient struct {
|
||||
Client *MySQLClient
|
||||
entry *MySQLPoolEntry
|
||||
pool *MySQLConnectionPool
|
||||
fromPool bool
|
||||
}
|
||||
|
||||
// Release 释放连接回连接池
|
||||
func (pc *PooledClient) Release() {
|
||||
if pc.fromPool && pc.pool != nil && pc.entry != nil {
|
||||
pc.pool.Release(pc.entry)
|
||||
}
|
||||
}
|
||||
|
||||
// GetMySQLClient 获取或创建 MySQL 客户端(使用连接池)
|
||||
func (p *ConnectionPool) GetMySQLClient(conn *models.DbConnection) (*MySQLClient, error) {
|
||||
func (p *ConnectionPool) GetMySQLClient(conn *models.DbConnection) *PooledClient {
|
||||
p.mu.Lock()
|
||||
defer p.mu.Unlock()
|
||||
|
||||
@@ -57,16 +80,25 @@ func (p *ConnectionPool) GetMySQLClient(conn *models.DbConnection) (*MySQLClient
|
||||
if p.mysqlPool != nil {
|
||||
entry, err := p.mysqlPool.Acquire(conn)
|
||||
if err == nil {
|
||||
// 成功从池中获取连接
|
||||
return entry.Client, nil
|
||||
return &PooledClient{Client: entry.Client, entry: entry, pool: p.mysqlPool, fromPool: true}
|
||||
}
|
||||
|
||||
// 连接池错误,返回
|
||||
return nil, err
|
||||
p.logPoolError("Acquire failed", err)
|
||||
}
|
||||
|
||||
// 降级到原有逻辑(如果连接池未初始化)
|
||||
return p.getMySQLClientLegacy(conn)
|
||||
// 降级到原有逻辑
|
||||
client, err := p.getMySQLClientLegacy(conn)
|
||||
if err != nil {
|
||||
return &PooledClient{Client: nil, fromPool: false}
|
||||
}
|
||||
return &PooledClient{Client: client, fromPool: false}
|
||||
}
|
||||
|
||||
// logPoolError 记录连接池错误
|
||||
func (p *ConnectionPool) logPoolError(operation string, err error) {
|
||||
if p.queryOptimizer != nil {
|
||||
// 通过查询优化器记录错误
|
||||
p.queryOptimizer.RecordPoolError(operation, err)
|
||||
}
|
||||
}
|
||||
|
||||
// getMySQLClientLegacy 原有的 MySQL 客户端获取逻辑(向后兼容)
|
||||
@@ -115,6 +147,92 @@ func (p *ConnectionPool) GetMySQLPoolStats() *PoolStats {
|
||||
return nil
|
||||
}
|
||||
|
||||
// OptimizeQuery 优化查询执行
|
||||
func (p *ConnectionPool) OptimizeQuery(ctx context.Context, conn *models.DbConnection, sqlStr string, database string) (*QueryResult, time.Duration, error) {
|
||||
pc := p.GetMySQLClient(conn)
|
||||
if pc.Client == nil {
|
||||
return nil, 0, fmt.Errorf("获取 MySQL 连接失败")
|
||||
}
|
||||
defer pc.Release()
|
||||
|
||||
// 使用查询优化器
|
||||
if p.queryOptimizer != nil {
|
||||
return p.queryOptimizer.OptimizeQuery(ctx, pc.Client, sqlStr, database)
|
||||
}
|
||||
|
||||
// 降级到普通查询
|
||||
startTime := time.Now()
|
||||
result, err := pc.Client.ExecuteQuery(ctx, sqlStr, database)
|
||||
duration := time.Since(startTime)
|
||||
return result, duration, err
|
||||
}
|
||||
|
||||
// ExecuteOptimizedUpdate 执行优化的更新操作
|
||||
func (p *ConnectionPool) ExecuteOptimizedUpdate(ctx context.Context, conn *models.DbConnection, sqlStr string, database string) (int64, time.Duration, error) {
|
||||
pc := p.GetMySQLClient(conn)
|
||||
if pc.Client == nil {
|
||||
return 0, 0, fmt.Errorf("获取 MySQL 连接失败")
|
||||
}
|
||||
defer pc.Release()
|
||||
|
||||
// 使用查询优化器
|
||||
if p.queryOptimizer != nil {
|
||||
return p.queryOptimizer.ExecuteOptimizedUpdate(ctx, pc.Client, sqlStr, database)
|
||||
}
|
||||
|
||||
// 降级到普通更新
|
||||
startTime := time.Now()
|
||||
result, err := pc.Client.ExecuteUpdate(ctx, sqlStr, database)
|
||||
duration := time.Since(startTime)
|
||||
return result, duration, err
|
||||
}
|
||||
|
||||
// GetQueryStats 获取查询统计信息
|
||||
func (p *ConnectionPool) GetQueryStats() QueryStats {
|
||||
if p.queryOptimizer != nil {
|
||||
return p.queryOptimizer.GetQueryStats()
|
||||
}
|
||||
return QueryStats{}
|
||||
}
|
||||
|
||||
// GetSlowQueries 获取慢查询记录
|
||||
func (p *ConnectionPool) GetSlowQueries(limit int) []SlowQuery {
|
||||
if p.queryOptimizer != nil {
|
||||
return p.queryOptimizer.GetSlowQueries(limit)
|
||||
}
|
||||
return []SlowQuery{}
|
||||
}
|
||||
|
||||
// GetIndexSuggestions 获取索引建议
|
||||
func (p *ConnectionPool) GetIndexSuggestions(table string) []IndexSuggestion {
|
||||
if p.queryOptimizer != nil {
|
||||
return p.queryOptimizer.GetIndexSuggestions(table)
|
||||
}
|
||||
return []IndexSuggestion{}
|
||||
}
|
||||
|
||||
// GenerateIndexSuggestions 为表生成索引建议
|
||||
func (p *ConnectionPool) GenerateIndexSuggestions(ctx context.Context, conn *models.DbConnection, database, table string) error {
|
||||
pc := p.GetMySQLClient(conn)
|
||||
if pc.Client == nil {
|
||||
return fmt.Errorf("获取 MySQL 连接失败")
|
||||
}
|
||||
defer pc.Release()
|
||||
|
||||
// 使用查询优化器
|
||||
if p.queryOptimizer != nil {
|
||||
return p.queryOptimizer.GenerateIndexSuggestions(ctx, pc.Client, database, table)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// ClearQueryCache 清空查询缓存
|
||||
func (p *ConnectionPool) ClearQueryCache() {
|
||||
if p.queryOptimizer != nil {
|
||||
p.queryOptimizer.ClearCache()
|
||||
}
|
||||
}
|
||||
|
||||
// GetRedisClient 获取或创建 Redis 客户端
|
||||
func (p *ConnectionPool) GetRedisClient(conn *models.DbConnection) (*RedisClient, error) {
|
||||
p.mu.Lock()
|
||||
|
||||
Reference in New Issue
Block a user