添加MongoDB认证支持并优化序列号生成工具

This commit is contained in:
2026-02-26 17:47:19 +08:00
committed by 张斌
parent a330577740
commit add07d47f1
3 changed files with 65 additions and 2 deletions

View File

@@ -8,6 +8,7 @@ package mongo
import ( import (
"context" "context"
"fmt" "fmt"
"net/url"
"os" "os"
"os/signal" "os/signal"
"strings" "strings"
@@ -34,6 +35,8 @@ type DataSourceConfig struct {
Name string `json:"name"` Name string `json:"name"`
Address string `json:"address"` Address string `json:"address"`
Database string `json:"database"` Database string `json:"database"`
Username string `json:"username"`
Password string `json:"password"`
MaxPoolSize int32 `json:"maxPoolSize"` MaxPoolSize int32 `json:"maxPoolSize"`
MinPoolSize int32 `json:"minPoolSize"` MinPoolSize int32 `json:"minPoolSize"`
ConnectTimeout time.Duration `json:"connectTimeout"` ConnectTimeout time.Duration `json:"connectTimeout"`
@@ -110,9 +113,25 @@ func (d *BaseDataSource) Connect(ctx context.Context) error {
dbName = gstr.SubStr(dbName, 0, strings.Index(dbName, "?")) dbName = gstr.SubStr(dbName, 0, strings.Index(dbName, "?"))
} }
// 构建连接URI
connectionURI := fmt.Sprintf("mongodb://%s", d.config.Address)
// 如果配置了用户名和密码添加到URI中
if d.config.Username != "" {
// URL编码用户名和密码正确处理特殊字符
encodedUsername := url.QueryEscape(d.config.Username)
encodedPassword := url.QueryEscape(d.config.Password)
// 构建认证信息
authInfo := fmt.Sprintf("%s:%s@", encodedUsername, encodedPassword)
// 将认证信息插入到URI中
connectionURI = fmt.Sprintf("mongodb://%s%s", authInfo, d.config.Address)
}
// 构建连接选项 // 构建连接选项
opt := options.Client(). opt := options.Client().
ApplyURI(d.config.Address). ApplyURI(connectionURI).
SetMaxPoolSize(uint64(d.config.MaxPoolSize)). SetMaxPoolSize(uint64(d.config.MaxPoolSize)).
SetMinPoolSize(uint64(d.config.MinPoolSize)). SetMinPoolSize(uint64(d.config.MinPoolSize)).
SetConnectTimeout(d.config.ConnectTimeout). SetConnectTimeout(d.config.ConnectTimeout).
@@ -302,6 +321,8 @@ func (m *DataSourceManager) InitializeFromConfig(ctx context.Context) error {
Name: name, Name: name,
Address: gconv.String(address), Address: gconv.String(address),
Database: gconv.String(subMap["database"]), Database: gconv.String(subMap["database"]),
Username: gconv.String(subMap["username"]),
Password: gconv.String(subMap["password"]),
MaxPoolSize: int32(gconv.Int(subMap["maxPoolSize"])), MaxPoolSize: int32(gconv.Int(subMap["maxPoolSize"])),
MinPoolSize: int32(gconv.Int(subMap["minPoolSize"])), MinPoolSize: int32(gconv.Int(subMap["minPoolSize"])),
ConnectTimeout: gconv.Duration(subMap["connectTimeout"]), ConnectTimeout: gconv.Duration(subMap["connectTimeout"]),

View File

@@ -57,7 +57,7 @@ func commandMonitor() *event.CommandMonitor {
fmt.Printf("[%s] 开始执行命令 | 数据库: %s | 集合: %s | 命令: %+v\n", fmt.Printf("[%s] 开始执行命令 | 数据库: %s | 集合: %s | 命令: %+v\n",
time.Now().Format("2006-01-02 15:04:05"), time.Now().Format("2006-01-02 15:04:05"),
evt.DatabaseName, evt.DatabaseName,
evt.Command.Lookup("collection").StringValue(), // 获取集合名 //evt.Command.Lookup("collection").StringValue(), // 获取集合名
evt.Command, evt.Command,
) )

View File

@@ -4,6 +4,7 @@ import (
"context" "context"
"encoding/json" "encoding/json"
"fmt" "fmt"
"github.com/gogf/gf/v2/os/gtime"
"net" "net"
"reflect" "reflect"
"sort" "sort"
@@ -339,3 +340,44 @@ func Struct(params any, pointer any) error {
} }
return nil return nil
} }
// IncrSequence 自增序列号 - 通用序列号工具
func IncrSequence(ctx context.Context, prefix string, incrLen int, seqSep string) (string, error) {
// 1. 校验incrLen合法性至少1位最多10位避免位数过大
if incrLen < 1 || incrLen > 8 {
g.Log().Warningf(ctx, "自增数位数[%d]不合法默认使用8位", incrLen)
incrLen = 8 // 兜底默认8位
}
// 2. 获取当前时间,格式化为"年月日"如20260226
timeStr := gtime.Now().Format("Ymd")
// 3. 拼接Redis的keyseq:前缀:时间字符串),确保每天一个独立的自增序列
redisKey := fmt.Sprintf("%s:%s:%s", "SEQ", prefix, timeStr)
// 4. 调用Redis的Incr做自增失败则生成兜底序列号
seqNum, err := g.Redis().Incr(ctx, redisKey)
if err != nil {
return "", fmt.Errorf("redis自增失败: %w", err)
}
// 5. 自动清理过期key定时任务
// 6. 校验自增数是否超过incrLen位上限超过则取模避免格式混乱
maxSeq := intPow10(incrLen) - 1
if seqNum > int64(maxSeq) {
return "", fmt.Errorf("自增数[%d]超过%d位上限[%d]", seqNum, incrLen, maxSeq)
}
// 7. 格式化自增数为指定位数,不足补零
seqFormat := fmt.Sprintf("%%0%dd", incrLen) // 动态生成格式化字符串
seqStr := fmt.Sprintf(seqFormat, seqNum)
// 8. 拼接最终序列号
finalSeq := fmt.Sprintf("%s%s%s%s%s", prefix, seqSep, timeStr, seqSep, seqStr)
return finalSeq, nil
}
// intPow10 计算10的n次方辅助函数如intPow10(6)=1000000
func intPow10(n int) int {
result := 1
for i := 0; i < n; i++ {
result *= 10
}
return result
}