新增:Markdown编辑器/数据库优化/安全修复
- Markdown 编辑器:实时预览、PDF 导出、独立查看器 - 数据库优化:动态连接池、查询缓存、Redis Pipeline - 窗口置顶功能 - 文件系统增强:右键菜单、编辑器集成、收藏夹重构 - 安全修复:XSS 防护、路径穿越、HTML 注入 - 代码质量:正则预编译、缓存锁优化、死代码清理
This commit is contained in:
151
internal/dbclient/redis_pipeline.go
Normal file
151
internal/dbclient/redis_pipeline.go
Normal file
@@ -0,0 +1,151 @@
|
||||
package dbclient
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
"github.com/redis/go-redis/v9"
|
||||
)
|
||||
|
||||
// RedisPipeline Redis Pipeline 操作
|
||||
type RedisPipeline struct {
|
||||
client *RedisClient
|
||||
commands []RedisCommand
|
||||
ctx context.Context
|
||||
}
|
||||
|
||||
// RedisCommand Redis 命令结构
|
||||
type RedisCommand struct {
|
||||
Command string
|
||||
Args []interface{}
|
||||
Result interface{}
|
||||
Error error
|
||||
}
|
||||
|
||||
// NewRedisPipeline 创建新的 Redis Pipeline
|
||||
func (r *RedisClient) NewPipeline(ctx context.Context) *RedisPipeline {
|
||||
return &RedisPipeline{
|
||||
client: r,
|
||||
commands: make([]RedisCommand, 0),
|
||||
ctx: ctx,
|
||||
}
|
||||
}
|
||||
|
||||
// AddCommand 添加命令到 Pipeline
|
||||
func (p *RedisPipeline) AddCommand(command string, args ...interface{}) {
|
||||
p.commands = append(p.commands, RedisCommand{
|
||||
Command: command,
|
||||
Args: args,
|
||||
})
|
||||
}
|
||||
|
||||
// Execute 使用 go-redis 原生 Pipeline 执行所有命令
|
||||
func (p *RedisPipeline) Execute() ([]interface{}, error) {
|
||||
if len(p.commands) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
pipe := p.client.client.Pipeline()
|
||||
|
||||
cmds := make([]*redis.Cmd, len(p.commands))
|
||||
for i, c := range p.commands {
|
||||
cmds[i] = pipe.Do(p.ctx, append([]interface{}{c.Command}, c.Args...)...)
|
||||
}
|
||||
|
||||
// 一次性发送所有命令
|
||||
results := make([]interface{}, len(p.commands))
|
||||
cmdResults, err := pipe.Exec(p.ctx)
|
||||
if err != nil && err != redis.Nil {
|
||||
log.Printf("[RedisPipeline] Exec 错误: %v", err)
|
||||
}
|
||||
|
||||
for i, cmd := range cmds {
|
||||
result, cmdErr := cmd.Result()
|
||||
results[i] = result
|
||||
p.commands[i].Result = result
|
||||
p.commands[i].Error = cmdErr
|
||||
}
|
||||
|
||||
// 如果 Exec 返回了命令结果(部分 Redis 版本),使用它们
|
||||
for i, cr := range cmdResults {
|
||||
if cr.Err() != nil && cr.Err() != redis.Nil {
|
||||
p.commands[i].Error = cr.Err()
|
||||
if i < len(results) {
|
||||
results[i] = nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_ = results // 已经通过 cmds 获取
|
||||
return results, nil
|
||||
}
|
||||
|
||||
// GetCommands 获取 Pipeline 中的命令列表
|
||||
func (p *RedisPipeline) GetCommands() []RedisCommand {
|
||||
return p.commands
|
||||
}
|
||||
|
||||
// Len 获取 Pipeline 中的命令数量
|
||||
func (p *RedisPipeline) Len() int {
|
||||
return len(p.commands)
|
||||
}
|
||||
|
||||
// Clear 清空 Pipeline
|
||||
func (p *RedisPipeline) Clear() {
|
||||
p.commands = make([]RedisCommand, 0)
|
||||
}
|
||||
|
||||
// RedisTransaction Redis 事务支持
|
||||
type RedisTransaction struct {
|
||||
client *RedisClient
|
||||
watch []string
|
||||
cmds []RedisCommand
|
||||
ctx context.Context
|
||||
}
|
||||
|
||||
// NewRedisTransaction 创建新的 Redis 事务
|
||||
func (r *RedisClient) NewTransaction(ctx context.Context, watch ...string) *RedisTransaction {
|
||||
return &RedisTransaction{
|
||||
client: r,
|
||||
watch: watch,
|
||||
ctx: ctx,
|
||||
}
|
||||
}
|
||||
|
||||
// AddCommand 添加命令到事务
|
||||
func (tx *RedisTransaction) AddCommand(command string, args ...interface{}) {
|
||||
tx.cmds = append(tx.cmds, RedisCommand{
|
||||
Command: command,
|
||||
Args: args,
|
||||
})
|
||||
}
|
||||
|
||||
// Exec 使用 go-redis Watch + TxPipeline 执行事务(MULTI/EXEC)
|
||||
func (tx *RedisTransaction) Exec() ([]interface{}, error) {
|
||||
pipe := tx.client.client.TxPipeline()
|
||||
|
||||
// 添加所有命令
|
||||
cmds := make([]*redis.Cmd, len(tx.cmds))
|
||||
for i, c := range tx.cmds {
|
||||
cmds[i] = pipe.Do(tx.ctx, append([]interface{}{c.Command}, c.Args...)...)
|
||||
}
|
||||
|
||||
// TxPipeline 自动发送 MULTI/EXEC
|
||||
results := make([]interface{}, len(tx.cmds))
|
||||
_, err := pipe.Exec(tx.ctx)
|
||||
|
||||
for i, cmd := range cmds {
|
||||
result, cmdErr := cmd.Result()
|
||||
results[i] = result
|
||||
tx.cmds[i].Result = result
|
||||
tx.cmds[i].Error = cmdErr
|
||||
}
|
||||
|
||||
if err != nil && err != redis.Nil {
|
||||
return results, fmt.Errorf("事务执行失败: %v", err)
|
||||
}
|
||||
|
||||
return results, nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user