Files
mayfly-go/server/internal/redis/application/redis.go

236 lines
6.7 KiB
Go
Raw Normal View History

package application
import (
"context"
"mayfly-go/internal/common/consts"
2024-03-02 19:08:19 +08:00
flowapp "mayfly-go/internal/flow/application"
flowentity "mayfly-go/internal/flow/domain/entity"
2022-09-09 18:26:08 +08:00
"mayfly-go/internal/redis/domain/entity"
"mayfly-go/internal/redis/domain/repository"
"mayfly-go/internal/redis/rdm"
tagapp "mayfly-go/internal/tag/application"
tagenttiy "mayfly-go/internal/tag/domain/entity"
"mayfly-go/pkg/base"
"mayfly-go/pkg/errorx"
2024-03-02 19:08:19 +08:00
"mayfly-go/pkg/logx"
"mayfly-go/pkg/model"
2024-03-02 19:08:19 +08:00
"mayfly-go/pkg/utils/jsonx"
"mayfly-go/pkg/utils/stringx"
2022-09-29 13:14:50 +08:00
"strconv"
"strings"
2024-03-02 19:08:19 +08:00
"github.com/redis/go-redis/v9"
)
2024-03-02 19:08:19 +08:00
type RunCmdParam struct {
Id uint64 `json:"id"`
Db int `json:"db"`
Cmd []any `json:"cmd"`
Remark string
}
type Redis interface {
base.App[*entity.Redis]
2024-03-02 19:08:19 +08:00
flowapp.FlowBizHandler
// 分页获取机器脚本信息列表
GetPageList(condition *entity.RedisQuery, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error)
// 测试连接
TestConn(re *entity.Redis) error
SaveRedis(ctx context.Context, re *entity.Redis, tagIds ...uint64) error
// 删除数据库信息
Delete(ctx context.Context, id uint64) error
// 获取数据库连接实例
2022-09-29 13:14:50 +08:00
// id: 数据库实例id
// db: 库号
GetRedisConn(id uint64, db int) (*rdm.RedisConn, error)
2024-03-02 19:08:19 +08:00
// 执行redis命令
RunCmd(ctx context.Context, redisConn *rdm.RedisConn, cmdParam *RunCmdParam) (any, error)
}
2022-09-09 18:26:08 +08:00
type redisAppImpl struct {
base.AppImpl[*entity.Redis, repository.Redis]
2024-03-02 19:08:19 +08:00
tagApp tagapp.TagTree `inject:"TagTreeApp"`
procinstApp flowapp.Procinst `inject:"ProcinstApp"`
2024-01-21 22:52:20 +08:00
}
// 注入RedisRepo
func (r *redisAppImpl) InjectRedisRepo(repo repository.Redis) {
r.Repo = repo
}
// 分页获取redis列表
func (r *redisAppImpl) GetPageList(condition *entity.RedisQuery, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error) {
return r.GetRepo().GetRedisList(condition, pageParam, toEntity, orderBy...)
}
func (r *redisAppImpl) TestConn(re *entity.Redis) error {
db := 0
if re.Db != "" {
db, _ = strconv.Atoi(strings.Split(re.Db, ",")[0])
}
rc, err := re.ToRedisInfo(db).Conn()
if err != nil {
return err
}
rc.Close()
return nil
}
func (r *redisAppImpl) SaveRedis(ctx context.Context, re *entity.Redis, tagIds ...uint64) error {
// 查找是否存在该库
oldRedis := &entity.Redis{
Host: re.Host,
SshTunnelMachineId: re.SshTunnelMachineId,
2023-03-17 09:46:41 +08:00
}
err := r.GetBy(oldRedis)
if re.Id == 0 {
if err == nil {
return errorx.NewBiz("该实例已存在")
}
2024-04-06 18:19:17 +08:00
if r.CountByCond(&entity.Redis{Code: re.Code}) > 0 {
return errorx.NewBiz("该编码已存在")
}
if errEnc := re.PwdEncrypt(); errEnc != nil {
return errorx.NewBiz(errEnc.Error())
}
return r.Tx(ctx, func(ctx context.Context) error {
return r.Insert(ctx, re)
}, func(ctx context.Context) error {
2024-04-06 18:19:17 +08:00
return r.tagApp.SaveResource(ctx, &tagapp.SaveResourceTagParam{
ResourceType: tagenttiy.TagTypeRedis,
2024-04-06 18:19:17 +08:00
ResourceCode: re.Code,
TagIds: tagIds,
})
})
}
// 如果存在该库,则校验修改的库是否为该库
if err == nil && oldRedis.Id != re.Id {
return errorx.NewBiz("该实例已存在")
}
// 如果修改了redis实例的库信息则关闭旧库的连接
2024-03-02 19:08:19 +08:00
if oldRedis.Db != re.Db || oldRedis.SshTunnelMachineId != re.SshTunnelMachineId || oldRedis.FlowProcdefKey != re.FlowProcdefKey {
for _, dbStr := range strings.Split(oldRedis.Db, ",") {
db, _ := strconv.Atoi(dbStr)
rdm.CloseConn(re.Id, db)
}
}
2023-12-20 23:01:51 +08:00
// 如果调整了ssh等会查不到旧数据故需要根据id获取旧信息将code赋值给标签进行关联
if oldRedis.Code == "" {
oldRedis, _ = r.GetById(new(entity.Redis), re.Id)
}
if errEnc := re.PwdEncrypt(); errEnc != nil {
return errorx.NewBiz(errEnc.Error())
}
2024-04-06 18:19:17 +08:00
re.Code = ""
return r.Tx(ctx, func(ctx context.Context) error {
return r.UpdateById(ctx, re)
}, func(ctx context.Context) error {
2024-04-06 18:19:17 +08:00
return r.tagApp.SaveResource(ctx, &tagapp.SaveResourceTagParam{
ResourceType: tagenttiy.TagTypeRedis,
2024-04-06 18:19:17 +08:00
ResourceCode: oldRedis.Code,
TagIds: tagIds,
})
})
}
// 删除Redis信息
func (r *redisAppImpl) Delete(ctx context.Context, id uint64) error {
re, err := r.GetById(new(entity.Redis), id)
if err != nil {
return errorx.NewBiz("该redis信息不存在")
}
2022-09-29 13:14:50 +08:00
// 如果存在连接,则关闭所有库连接信息
for _, dbStr := range strings.Split(re.Db, ",") {
db, _ := strconv.Atoi(dbStr)
rdm.CloseConn(re.Id, db)
2022-09-29 13:14:50 +08:00
}
return r.Tx(ctx, func(ctx context.Context) error {
return r.DeleteById(ctx, id)
}, func(ctx context.Context) error {
2024-04-06 18:19:17 +08:00
return r.tagApp.SaveResource(ctx, &tagapp.SaveResourceTagParam{
ResourceType: tagenttiy.TagTypeRedis,
2024-04-06 18:19:17 +08:00
ResourceCode: re.Code,
})
})
}
// 获取数据库连接实例
func (r *redisAppImpl) GetRedisConn(id uint64, db int) (*rdm.RedisConn, error) {
return rdm.GetRedisConn(id, db, func() (*rdm.RedisInfo, error) {
// 缓存不存在则回调获取redis信息
re, err := r.GetById(new(entity.Redis), id)
if err != nil {
return nil, errorx.NewBiz("redis信息不存在")
}
if err := re.PwdDecrypt(); err != nil {
return nil, errorx.NewBiz(err.Error())
}
return re.ToRedisInfo(db, r.tagApp.ListTagPathByResource(consts.TagResourceTypeRedis, re.Code)...), nil
})
}
2024-03-02 19:08:19 +08:00
func (r *redisAppImpl) RunCmd(ctx context.Context, redisConn *rdm.RedisConn, cmdParam *RunCmdParam) (any, error) {
if redisConn == nil {
return nil, errorx.NewBiz("redis连接不存在")
}
// 开启工单流程,并且为写入命令,则开启对应审批流程
if procdefKey := redisConn.Info.FlowProcdefKey; procdefKey != "" && rdm.IsWriteCmd(cmdParam.Cmd[0]) {
_, err := r.procinstApp.StartProc(ctx, procdefKey, &flowapp.StarProcParam{
BizType: RedisRunWriteCmdFlowBizType,
BizKey: stringx.Rand(24),
BizForm: jsonx.ToStr(cmdParam),
Remark: cmdParam.Remark,
})
if err != nil {
return nil, err
}
return nil, nil
}
res, err := redisConn.RunCmd(ctx, cmdParam.Cmd...)
// 获取的key不存在不报错
if err == redis.Nil {
return nil, nil
}
return res, err
}
func (r *redisAppImpl) FlowBizHandle(ctx context.Context, bizHandleParam *flowapp.BizHandleParam) error {
bizKey := bizHandleParam.BizKey
procinstStatus := bizHandleParam.ProcinstStatus
logx.Debugf("RedisRunWriteCmd FlowBizHandle -> bizKey: %s, procinstStatus: %s", bizKey, flowentity.ProcinstStatusEnum.GetDesc(procinstStatus))
// 流程非完成状态,不处理
if procinstStatus != flowentity.ProcinstStatusCompleted {
return nil
}
runCmdParam, err := jsonx.To(bizHandleParam.BizForm, new(RunCmdParam))
if err != nil {
return errorx.NewBiz("业务表单信息解析失败: %s", err.Error())
}
redisConn, err := r.GetRedisConn(runCmdParam.Id, runCmdParam.Db)
if err != nil {
return err
}
_, err = redisConn.RunCmd(ctx, runCmdParam.Cmd...)
return err
}