diff --git a/internal/logic/core/editresourcespeclogic.go b/internal/logic/core/editresourcespeclogic.go index f355a707..5e668f42 100644 --- a/internal/logic/core/editresourcespeclogic.go +++ b/internal/logic/core/editresourcespeclogic.go @@ -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 +} diff --git a/internal/scheduler/service/utils/jcs/middleware.go b/internal/scheduler/service/utils/jcs/middleware.go index c0a6a78a..31755f62 100644 --- a/internal/scheduler/service/utils/jcs/middleware.go +++ b/internal/scheduler/service/utils/jcs/middleware.go @@ -48,7 +48,7 @@ func StatusReport(url string, report interface{}) error { Post(url) bodyStr, _ := jsoniter.MarshalToString(report) - log.Debug().Msgf("任务状态上报到中间件请求参数:[%v], 返回值: [%v]", bodyStr, string(rp.Body())) + log.Debug().Msgf("上报任务状态到中间件,请求url:%s, 请求参数:%s, 响应结果:%s", url, bodyStr, string(rp.Body())) if err != nil { logx.Errorf("############ Report Status Message Error %s", err.Error()) diff --git a/pkg/models/tbaseresourcespecmodel_gen.go b/pkg/models/tbaseresourcespecmodel_gen.go index 2bad60a8..f89d9371 100755 --- a/pkg/models/tbaseresourcespecmodel_gen.go +++ b/pkg/models/tbaseresourcespecmodel_gen.go @@ -46,7 +46,7 @@ type ( TotalUnit string `db:"total_unit" json:"totalUnit,omitempty"` // 总量值单位(GB/core等) AvailableValue float64 `db:"available_value" json:"availableValue,omitempty"` // 可用值 AvailableUnit string `db:"available_unit" json:"availableUnit,omitempty"` // 可用值单位(GB/core等) - UserId int64 `db:"user_id" json:"userId"` // 用户ID + UserId int64 `db:"user_id" json:"userId,omitempty"` // 用户ID CreateTime time.Time `db:"create_time" json:"createTime"` // 创建时间 UpdateTime time.Time `db:"update_time" json:"updateTime"` // 更新时间 DeletedAt gorm.DeletedAt `db:"deleted_at" json:"-"` // 删除时间 diff --git a/pkg/models/tresourcespecmodel_gen.go b/pkg/models/tresourcespecmodel_gen.go index 3aebafe7..b4a83131 100755 --- a/pkg/models/tresourcespecmodel_gen.go +++ b/pkg/models/tresourcespecmodel_gen.go @@ -49,7 +49,7 @@ type ( ClusterId int64 `db:"cluster_id" json:"clusterId,string,omitempty"` // 集群ID CostPerUnit float64 `db:"cost_per_unit" json:"costPerUnit,omitempty"` // 单位时间积分消耗 CostType string `db:"cost_type" json:"costType,omitempty"` // 计费类型(hourly, daily, monthly,perUse) - UserId int64 `db:"user_id" json:"userId"` // 用户ID + UserId int64 `db:"user_id" json:"userId,omitempty"` // 用户ID CreateTime time.Time `db:"create_time" json:"createTime"` // 创建时间 UpdateTime time.Time `db:"update_time" json:"updateTime"` // 更新时间 DeletedAt gorm.DeletedAt `db:"deleted_at" json:"-"` // 删除时间