Files
mayfly-go/server/internal/db/dbm/dbi/db_info.go

149 lines
3.9 KiB
Go
Raw Normal View History

package dbi
import (
2025-05-22 23:29:50 +08:00
"context"
"fmt"
machineapp "mayfly-go/internal/machine/application"
2024-01-13 13:38:53 +08:00
"mayfly-go/internal/machine/mcm"
"mayfly-go/pkg/errorx"
"mayfly-go/pkg/logx"
2025-02-27 19:40:31 +08:00
"mayfly-go/pkg/model"
2024-03-11 20:04:20 +08:00
"strings"
)
2024-03-15 13:31:53 +08:00
type DbType string
func ToDbType(dbType string) DbType {
return DbType(dbType)
}
func (dbType DbType) Equal(typ string) bool {
return ToDbType(typ) == dbType
}
type DbInfo struct {
2025-02-27 19:40:31 +08:00
model.ExtraData // 连接需要的其他额外参数json字符串如oracle数据库需要指定sid等
2023-12-20 17:29:16 +08:00
InstanceId uint64 // 实例id
Id uint64 // dbId
Name string
Type DbType // 类型mysql postgres等
Host string
Port int
Network string
Username string
Password string
Params string
2024-03-15 13:31:53 +08:00
Database string // 若有schema的库则为'database/scheam'格式
Version DbVersion // 数据库版本信息,用于语法兼容
DefaultVersion bool // 经过查询数据库版本信息后,是否仍然使用默认版本
CodePath []string
SshTunnelMachineId int
2024-12-08 13:04:23 +08:00
useSshTunnel bool // 是否使用系统自己实现的ssh隧道连接,而非库自带的
Meta Meta
}
// 获取记录日志的描述
func (di *DbInfo) GetLogDesc() string {
return fmt.Sprintf("DB[id=%d, tag=%s, name=%s, ip=%s:%d, database=%s]", di.Id, di.CodePath, di.Name, di.Host, di.Port, di.Database)
}
// 连接数据库
2025-05-22 23:29:50 +08:00
func (di *DbInfo) Conn(ctx context.Context, meta Meta) (*DbConn, error) {
if meta == nil {
2024-11-20 22:43:53 +08:00
return nil, errorx.NewBiz("the database meta information interface cannot be empty")
}
// 赋值Meta方便后续获取dialect等
di.Meta = meta
database := di.Database
2024-03-15 13:31:53 +08:00
// 如果数据库为空,则使用默认数据库进行连接
if database == "" {
database = meta.GetMetadata(&DbConn{Info: di}).GetDefaultDb()
di.Database = database
2024-03-15 13:31:53 +08:00
}
2025-05-22 23:29:50 +08:00
conn, err := meta.GetSqlDb(ctx, di)
if err != nil {
logx.Errorf("db connection failed: %s:%d/%s, err:%s", di.Host, di.Port, database, err.Error())
return nil, errorx.NewBizf("db connection failed: %s", err.Error())
}
err = conn.Ping()
if err != nil {
logx.Errorf("db ping failed: %s:%d/%s, err:%s", di.Host, di.Port, database, err.Error())
return nil, errorx.NewBizf("db connection failed: %s", err.Error())
}
dbc := &DbConn{Id: GetDbConnId(di.Id, database), Info: di}
// 最大连接周期超过时间的连接就close
// conn.SetConnMaxLifetime(100 * time.Second)
// 设置最大连接数
2025-05-22 23:29:50 +08:00
conn.SetMaxOpenConns(6)
// 设置闲置连接数
conn.SetMaxIdleConns(1)
dbc.db = conn
logx.Infof("db connection: %s:%d/%s", di.Host, di.Port, database)
return dbc, nil
}
// 如果使用了ssh隧道将其host port改变其本地映射host port
2025-05-22 23:29:50 +08:00
func (di *DbInfo) IfUseSshTunnelChangeIpPort(ctx context.Context) error {
// 开启ssh隧道
if di.SshTunnelMachineId > 0 {
2025-05-22 23:29:50 +08:00
sshTunnelMachine, err := GetSshTunnel(ctx, di.SshTunnelMachineId)
if err != nil {
return err
}
exposedIp, exposedPort, err := sshTunnelMachine.OpenSshTunnel(fmt.Sprintf("db:%d", di.Id), di.Host, di.Port)
if err != nil {
return err
}
di.Host = exposedIp
di.Port = exposedPort
2024-12-08 13:04:23 +08:00
di.useSshTunnel = true
}
return nil
}
2024-03-15 13:31:53 +08:00
// 获取当前库的schema兼容 database/schema模式
2024-03-11 20:04:20 +08:00
func (di *DbInfo) CurrentSchema() string {
dbName := di.Database
schema := ""
arr := strings.Split(dbName, "/")
if len(arr) == 2 {
schema = arr[1]
}
return schema
}
2024-03-15 13:31:53 +08:00
// 获取当前数据库(兼容 database/schema模式
func (di *DbInfo) GetDatabase() string {
dbName := di.Database
ss := strings.Split(dbName, "/")
if len(ss) > 1 {
return ss[0]
}
return dbName
}
2024-01-13 13:38:53 +08:00
// 根据ssh tunnel机器id返回ssh tunnel
2025-05-22 23:29:50 +08:00
func GetSshTunnel(ctx context.Context, sshTunnelMachineId int) (*mcm.SshTunnelMachine, error) {
return machineapp.GetMachineApp().GetSshTunnelMachine(ctx, sshTunnelMachineId)
2024-01-13 13:38:53 +08:00
}
// 获取连接id
func GetDbConnId(dbId uint64, db string) string {
if dbId == 0 {
return ""
}
2025-05-22 23:29:50 +08:00
return fmt.Sprintf("db-%d:%s", dbId, db)
}