refactor: db/redis/mongo连接代码包独立

This commit is contained in:
meilin.huang
2023-10-27 17:41:45 +08:00
parent a1303b52eb
commit 12f63ef3dd
45 changed files with 1112 additions and 950 deletions

View File

@@ -1,26 +1,12 @@
package application
import (
"context"
"fmt"
"mayfly-go/internal/common/consts"
machineapp "mayfly-go/internal/machine/application"
"mayfly-go/internal/machine/infrastructure/machine"
"mayfly-go/internal/mongo/domain/entity"
"mayfly-go/internal/mongo/domain/repository"
"mayfly-go/internal/mongo/mgm"
"mayfly-go/pkg/base"
"mayfly-go/pkg/biz"
"mayfly-go/pkg/cache"
"mayfly-go/pkg/logx"
"mayfly-go/pkg/errorx"
"mayfly-go/pkg/model"
"mayfly-go/pkg/utils/netx"
"mayfly-go/pkg/utils/structx"
"net"
"regexp"
"time"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
)
type Mongo interface {
@@ -38,7 +24,7 @@ type Mongo interface {
// 获取mongo连接实例
// @param id mongo id
GetMongoInst(id uint64) *MongoInstance
GetMongoConn(id uint64) (*mgm.MongoConn, error)
}
func newMongoAppImpl(mongoRepo repository.Mongo) Mongo {
@@ -61,7 +47,7 @@ func (d *mongoAppImpl) Count(condition *entity.MongoQuery) int64 {
}
func (d *mongoAppImpl) Delete(id uint64) error {
DeleteMongoCache(id)
mgm.CloseConn(id)
return d.GetRepo().DeleteById(id)
}
@@ -71,148 +57,16 @@ func (d *mongoAppImpl) Save(m *entity.Mongo) error {
}
// 先关闭连接
DeleteMongoCache(m.Id)
mgm.CloseConn(m.Id)
return d.GetRepo().UpdateById(m)
}
func (d *mongoAppImpl) GetMongoInst(id uint64) *MongoInstance {
mongoInstance, err := GetMongoInstance(id, func(u uint64) (*entity.Mongo, error) {
mongo, err := d.GetById(new(entity.Mongo), u)
func (d *mongoAppImpl) GetMongoConn(id uint64) (*mgm.MongoConn, error) {
return mgm.GetMongoConn(id, func() (*mgm.MongoInfo, error) {
mongo, err := d.GetById(new(entity.Mongo), id)
if err != nil {
return nil, err
return nil, errorx.NewBiz("mongo信息不存在")
}
return mongo, nil
})
biz.ErrIsNilAppendErr(err, "连接mongo失败: %s")
return mongoInstance
}
// -----------------------------------------------------------
// mongo客户端连接缓存指定时间内没有访问则会被关闭
var mongoCliCache = cache.NewTimedCache(consts.MongoConnExpireTime, 5*time.Second).
WithUpdateAccessTime(true).
OnEvicted(func(key any, value any) {
logx.Infof("删除mongo连接缓存: id = %v", key)
value.(*MongoInstance).Close()
})
func init() {
machine.AddCheckSshTunnelMachineUseFunc(func(machineId int) bool {
// 遍历所有mongo连接实例若存在redis实例使用该ssh隧道机器则返回true表示还在使用中...
items := mongoCliCache.Items()
for _, v := range items {
if v.Value.(*MongoInstance).Info.SshTunnelMachineId == machineId {
return true
}
}
return false
return mongo.ToMongoInfo(), nil
})
}
// 获取mongo的连接实例
func GetMongoInstance(mongoId uint64, getMongoEntity func(uint64) (*entity.Mongo, error)) (*MongoInstance, error) {
mi, err := mongoCliCache.ComputeIfAbsent(mongoId, func(_ any) (any, error) {
mongoEntity, err := getMongoEntity(mongoId)
if err != nil {
return nil, err
}
c, err := connect(mongoEntity)
if err != nil {
return nil, err
}
return c, nil
})
if mi != nil {
return mi.(*MongoInstance), err
}
return nil, err
}
func DeleteMongoCache(mongoId uint64) {
mongoCliCache.Delete(mongoId)
}
type MongoInfo struct {
Id uint64 `json:"id"`
Name string `json:"name"`
TagPath string `json:"tagPath"`
SshTunnelMachineId int `json:"-"` // ssh隧道机器id
}
func (m *MongoInfo) GetLogDesc() string {
return fmt.Sprintf("Mongo[id=%d, tag=%s, name=%s]", m.Id, m.TagPath, m.Name)
}
type MongoInstance struct {
Id uint64
Info *MongoInfo
Cli *mongo.Client
}
func (mi *MongoInstance) Close() {
if mi.Cli != nil {
if err := mi.Cli.Disconnect(context.Background()); err != nil {
logx.Errorf("关闭mongo实例[%d]连接失败: %s", mi.Id, err)
}
mi.Cli = nil
}
}
// 连接mongo并返回client
func connect(me *entity.Mongo) (*MongoInstance, error) {
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
mongoInstance := &MongoInstance{Id: me.Id, Info: toMongoInfo(me)}
mongoOptions := options.Client().ApplyURI(me.Uri).
SetMaxPoolSize(1)
// 启用ssh隧道则连接隧道机器
if me.SshTunnelMachineId > 0 {
mongoOptions.SetDialer(&MongoSshDialer{machineId: me.SshTunnelMachineId})
}
client, err := mongo.Connect(ctx, mongoOptions)
if err != nil {
mongoInstance.Close()
return nil, err
}
if err = client.Ping(context.TODO(), nil); err != nil {
mongoInstance.Close()
return nil, err
}
logx.Infof("连接mongo: %s", func(str string) string {
reg := regexp.MustCompile(`(^mongodb://.+?:)(.+)(@.+$)`)
return reg.ReplaceAllString(str, `${1}****${3}`)
}(me.Uri))
mongoInstance.Cli = client
return mongoInstance, err
}
func toMongoInfo(me *entity.Mongo) *MongoInfo {
mi := new(MongoInfo)
structx.Copy(mi, me)
return mi
}
type MongoSshDialer struct {
machineId int
}
func (sd *MongoSshDialer) DialContext(ctx context.Context, network, address string) (net.Conn, error) {
stm, err := machineapp.GetMachineApp().GetSshTunnelMachine(sd.machineId)
if err != nil {
return nil, err
}
if sshConn, err := stm.GetDialConn(network, address); err == nil {
// 将ssh conn包装否则内部部设置超时会报错,ssh conn不支持设置超时会返回错误: ssh: tcpChan: deadline not supported
return &netx.WrapSshConn{Conn: sshConn}, nil
} else {
return nil, err
}
}