|
|
|
@@ -2,13 +2,16 @@ package core |
|
|
|
|
|
|
|
import ( |
|
|
|
"context" |
|
|
|
"fmt" |
|
|
|
"github.com/mitchellh/mapstructure" |
|
|
|
"github.com/pkg/errors" |
|
|
|
"gitlink.org.cn/JointCloud/pcm-coordinator/pkg/models" |
|
|
|
|
|
|
|
"github.com/zeromicro/go-zero/core/logx" |
|
|
|
"gitlink.org.cn/JointCloud/pcm-coordinator/internal/svc" |
|
|
|
"gitlink.org.cn/JointCloud/pcm-coordinator/internal/types" |
|
|
|
|
|
|
|
"github.com/zeromicro/go-zero/core/logx" |
|
|
|
"gitlink.org.cn/JointCloud/pcm-coordinator/pkg/models" |
|
|
|
"reflect" |
|
|
|
"strconv" |
|
|
|
"time" |
|
|
|
) |
|
|
|
|
|
|
|
type EditResourceSpecLogic struct { |
|
|
|
@@ -26,29 +29,123 @@ func NewEditResourceSpecLogic(ctx context.Context, svcCtx *svc.ServiceContext) * |
|
|
|
} |
|
|
|
|
|
|
|
func (l *EditResourceSpecLogic) EditResourceSpec(req *types.ResourceSpec) (resp *types.CommonResp, err error) { |
|
|
|
//检查是否存在 |
|
|
|
var count int64 |
|
|
|
db := l.svcCtx.DbEngin.Model(&types.ResourceSpec{}).Table("t_resource_spec") |
|
|
|
err = db.Where("id = ? and deleted_at is null", req.Id).Count(&count).Error |
|
|
|
startTime := time.Now() |
|
|
|
resources, err := ConvertResourceSpec(req) |
|
|
|
l.Infof("转换主资源规格耗时:%v", time.Since(startTime)) |
|
|
|
if err != nil { |
|
|
|
return nil, err |
|
|
|
return nil, errors.Wrap(err, "资源规格转换失败") |
|
|
|
} |
|
|
|
if count == 0 { |
|
|
|
return nil, errors.New("资源规格不存在") |
|
|
|
|
|
|
|
tx := l.svcCtx.DbEngin.Begin() |
|
|
|
defer func() { |
|
|
|
if r := recover(); r != nil { |
|
|
|
tx.Rollback() |
|
|
|
panic(r) |
|
|
|
} |
|
|
|
}() |
|
|
|
|
|
|
|
// 检查主资源存在性 |
|
|
|
var existing models.TResourceSpec |
|
|
|
if err := tx.Model(&models.TResourceSpec{}). |
|
|
|
Where("id = ? AND deleted_at IS NULL", resources.Id). |
|
|
|
First(&existing). |
|
|
|
Error; err != nil { |
|
|
|
tx.Rollback() |
|
|
|
return nil, errors.Wrapf(err, "资源规格不存在 (ID: %d)", resources.Id) |
|
|
|
} |
|
|
|
resp = &types.CommonResp{} |
|
|
|
db = l.svcCtx.DbEngin.Model(&types.ResourceSpec{}).Table("t_resource_spec") |
|
|
|
err = db.Where("id = ?", req.Id).Save(req).Error |
|
|
|
if err != nil { |
|
|
|
return nil, err |
|
|
|
|
|
|
|
// 更新主资源 |
|
|
|
if err := tx.Model(&models.TResourceSpec{}). |
|
|
|
Where("id = ?", resources.Id). |
|
|
|
Select("*"). |
|
|
|
Updates(&resources). |
|
|
|
Error; err != nil { |
|
|
|
tx.Rollback() |
|
|
|
return nil, errors.Wrap(err, "更新主资源规格失败") |
|
|
|
} |
|
|
|
|
|
|
|
baseDb := l.svcCtx.DbEngin.Model(models.TBaseResourceSpec{}).Table("t_base_resource_spec") |
|
|
|
for _, spec := range req.BaseResourceSpecs { |
|
|
|
err = baseDb.Where("id = ?", spec.Id).Updates(&spec).Error |
|
|
|
if err != nil { |
|
|
|
return nil, err |
|
|
|
// 更新子资源 |
|
|
|
for _, spec := range resources.BaseResourceSpecs { |
|
|
|
spec.ResourceSpecId = resources.Id // 确保关联关系正确 |
|
|
|
result := tx.Model(&models.TBaseResourceSpec{}). |
|
|
|
Where("id = ? AND resource_spec_id = ?", spec.Id, resources.Id). |
|
|
|
Updates(&spec) |
|
|
|
if result.Error != nil { |
|
|
|
tx.Rollback() |
|
|
|
return nil, errors.Wrapf(result.Error, "更新子资源失败 (ID: %d)", spec.Id) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
if err := tx.Commit().Error; err != nil { |
|
|
|
return nil, errors.Wrap(err, "事务提交失败") |
|
|
|
} |
|
|
|
|
|
|
|
return resp, nil |
|
|
|
} |
|
|
|
|
|
|
|
// 类型转换相关函数保持不变,但建议添加更多错误处理 |
|
|
|
func decodeHook(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) { |
|
|
|
// 增强类型转换错误处理 |
|
|
|
switch { |
|
|
|
case f.Kind() == reflect.String && t.Kind() == reflect.Int64: |
|
|
|
v, err := strconv.ParseInt(data.(string), 10, 64) |
|
|
|
if err != nil { |
|
|
|
return nil, fmt.Errorf("类型转换失败: %v -> %v (%w)", f, t, err) |
|
|
|
} |
|
|
|
return v, nil |
|
|
|
case f.Kind() == reflect.String && t == reflect.TypeOf(time.Time{}): |
|
|
|
v, err := time.Parse(time.RFC3339, data.(string)) |
|
|
|
if err != nil { |
|
|
|
return nil, fmt.Errorf("时间格式解析失败: %w", err) |
|
|
|
} |
|
|
|
return v, nil |
|
|
|
case f.Kind() == reflect.Int32 && t.Kind() == reflect.Int64: |
|
|
|
return int64(data.(int32)), nil |
|
|
|
} |
|
|
|
return data, nil |
|
|
|
} |
|
|
|
|
|
|
|
func decodeWithHook(input, output interface{}) error { |
|
|
|
decoder, err := mapstructure.NewDecoder(&mapstructure.DecoderConfig{ |
|
|
|
DecodeHook: mapstructure.ComposeDecodeHookFunc( |
|
|
|
decodeHook, |
|
|
|
mapstructure.StringToTimeHookFunc(time.RFC3339), |
|
|
|
), |
|
|
|
Result: output, |
|
|
|
TagName: "json", |
|
|
|
}) |
|
|
|
if err != nil { |
|
|
|
return fmt.Errorf("创建解码器失败: %w", err) |
|
|
|
} |
|
|
|
if err := decoder.Decode(input); err != nil { |
|
|
|
return fmt.Errorf("数据解码失败: %w", err) |
|
|
|
} |
|
|
|
return nil |
|
|
|
} |
|
|
|
|
|
|
|
func convertBaseSpecs(specs []types.BaseResourceSpec) ([]models.TBaseResourceSpec, error) { |
|
|
|
tSpecs := make([]models.TBaseResourceSpec, 0, len(specs)) |
|
|
|
for i, spec := range specs { |
|
|
|
var tSpec models.TBaseResourceSpec |
|
|
|
if err := decodeWithHook(spec, &tSpec); err != nil { |
|
|
|
return nil, fmt.Errorf("基础资源规格转换失败 (索引 %d): %w", i, err) |
|
|
|
} |
|
|
|
tSpecs = append(tSpecs, tSpec) |
|
|
|
} |
|
|
|
return tSpecs, nil |
|
|
|
} |
|
|
|
|
|
|
|
func ConvertResourceSpec(spec *types.ResourceSpec) (models.TResourceSpec, error) { |
|
|
|
var tSpec models.TResourceSpec |
|
|
|
if err := decodeWithHook(spec, &tSpec); err != nil { |
|
|
|
return models.TResourceSpec{}, fmt.Errorf("主资源规格转换失败: %w", err) |
|
|
|
} |
|
|
|
|
|
|
|
baseSpecs, err := convertBaseSpecs(spec.BaseResourceSpecs) |
|
|
|
if err != nil { |
|
|
|
return models.TResourceSpec{}, fmt.Errorf("基础资源规格转换失败: %w", err) |
|
|
|
} |
|
|
|
tSpec.BaseResourceSpecs = baseSpecs |
|
|
|
|
|
|
|
return tSpec, nil |
|
|
|
} |