| @@ -16,20 +16,20 @@ func Test_JobSet(t *testing.T) { | |||||
| id, err := cli.JobSetSumbit(JobSetSumbitReq{ | id, err := cli.JobSetSumbit(JobSetSumbitReq{ | ||||
| JobSetInfo: models.JobSetInfo{ | JobSetInfo: models.JobSetInfo{ | ||||
| Jobs: []models.JobInfo{ | Jobs: []models.JobInfo{ | ||||
| models.ResourceJobInfo{ | |||||
| &models.ResourceJobInfo{ | |||||
| Type: models.JobTypeResource, | Type: models.JobTypeResource, | ||||
| }, | }, | ||||
| models.NormalJobInfo{ | |||||
| &models.NormalJobInfo{ | |||||
| Type: models.JobTypeNormal, | Type: models.JobTypeNormal, | ||||
| Files: models.JobFilesInfo{ | Files: models.JobFilesInfo{ | ||||
| Dataset: models.PackageJobFileInfo{ | |||||
| Dataset: &models.PackageJobFileInfo{ | |||||
| Type: models.FileInfoTypePackage, | Type: models.FileInfoTypePackage, | ||||
| }, | }, | ||||
| Code: models.LocalJobFileInfo{ | |||||
| Code: &models.LocalJobFileInfo{ | |||||
| Type: models.FileInfoTypeLocalFile, | Type: models.FileInfoTypeLocalFile, | ||||
| LocalPath: "code", | LocalPath: "code", | ||||
| }, | }, | ||||
| Image: models.ImageJobFileInfo{ | |||||
| Image: &models.ImageJobFileInfo{ | |||||
| Type: models.FileInfoTypeImage, | Type: models.FileInfoTypeImage, | ||||
| }, | }, | ||||
| }, | }, | ||||
| @@ -20,7 +20,9 @@ type JobSetInfo struct { | |||||
| Jobs []JobInfo `json:"jobs"` | Jobs []JobInfo `json:"jobs"` | ||||
| } | } | ||||
| type JobInfo interface{} | |||||
| type JobInfo interface { | |||||
| GetLocalJobID() string | |||||
| } | |||||
| var JobInfoTypeUnion = types.NewTypeUnion[JobInfo]( | var JobInfoTypeUnion = types.NewTypeUnion[JobInfo]( | ||||
| myreflect.TypeOf[NormalJobInfo](), | myreflect.TypeOf[NormalJobInfo](), | ||||
| @@ -28,16 +30,24 @@ var JobInfoTypeUnion = types.NewTypeUnion[JobInfo]( | |||||
| ) | ) | ||||
| var JobInfoTaggedTypeUnion = serder.NewTaggedTypeUnion(JobInfoTypeUnion, "Type", "type") | var JobInfoTaggedTypeUnion = serder.NewTaggedTypeUnion(JobInfoTypeUnion, "Type", "type") | ||||
| type JobInfoBase struct { | |||||
| LocalJobID string `json:"localJobID"` | |||||
| } | |||||
| func (i *JobInfoBase) GetLocalJobID() string { | |||||
| return i.LocalJobID | |||||
| } | |||||
| type NormalJobInfo struct { | type NormalJobInfo struct { | ||||
| LocalJobID string `json:"localJobID"` | |||||
| Type string `json:"type" union:"Normal"` | |||||
| Files JobFilesInfo `json:"files"` | |||||
| Runtime JobRuntimeInfo `json:"runtime"` | |||||
| Resources JobResourcesInfo `json:"resources"` | |||||
| JobInfoBase | |||||
| Type string `json:"type" union:"Normal"` | |||||
| Files JobFilesInfo `json:"files"` | |||||
| Runtime JobRuntimeInfo `json:"runtime"` | |||||
| Resources JobResourcesInfo `json:"resources"` | |||||
| } | } | ||||
| type ResourceJobInfo struct { | type ResourceJobInfo struct { | ||||
| LocalJobID string `json:"localJobID"` | |||||
| JobInfoBase | |||||
| Type string `json:"type" union:"Resource"` | Type string `json:"type" union:"Resource"` | ||||
| TargetLocalJobID string `json:"targetLocalJobID"` | TargetLocalJobID string `json:"targetLocalJobID"` | ||||
| } | } | ||||
| @@ -48,7 +58,9 @@ type JobFilesInfo struct { | |||||
| Image JobFileInfo `json:"image"` | Image JobFileInfo `json:"image"` | ||||
| } | } | ||||
| type JobFileInfo interface{} | |||||
| type JobFileInfo interface { | |||||
| Noop() | |||||
| } | |||||
| var FileInfoTypeUnion = types.NewTypeUnion[JobFileInfo]( | var FileInfoTypeUnion = types.NewTypeUnion[JobFileInfo]( | ||||
| myreflect.TypeOf[PackageJobFileInfo](), | myreflect.TypeOf[PackageJobFileInfo](), | ||||
| @@ -58,22 +70,30 @@ var FileInfoTypeUnion = types.NewTypeUnion[JobFileInfo]( | |||||
| ) | ) | ||||
| var FileInfoTaggedTypeUnion = serder.NewTaggedTypeUnion(FileInfoTypeUnion, "Type", "type") | var FileInfoTaggedTypeUnion = serder.NewTaggedTypeUnion(FileInfoTypeUnion, "Type", "type") | ||||
| type JobFileInfoBase struct{} | |||||
| func (i *JobFileInfoBase) Noop() {} | |||||
| type PackageJobFileInfo struct { | type PackageJobFileInfo struct { | ||||
| JobFileInfoBase | |||||
| Type string `json:"type" union:"Package"` | Type string `json:"type" union:"Package"` | ||||
| PackageID int64 `json:"packageID"` | PackageID int64 `json:"packageID"` | ||||
| } | } | ||||
| type LocalJobFileInfo struct { | type LocalJobFileInfo struct { | ||||
| JobFileInfoBase | |||||
| Type string `json:"type" union:"LocalFile"` | Type string `json:"type" union:"LocalFile"` | ||||
| LocalPath string `json:"localPath"` | LocalPath string `json:"localPath"` | ||||
| } | } | ||||
| type ResourceJobFileInfo struct { | type ResourceJobFileInfo struct { | ||||
| JobFileInfoBase | |||||
| Type string `json:"type" union:"Resource"` | Type string `json:"type" union:"Resource"` | ||||
| ResourceLocalJobID string `json:"resourceLocalJobID"` | ResourceLocalJobID string `json:"resourceLocalJobID"` | ||||
| } | } | ||||
| type ImageJobFileInfo struct { | type ImageJobFileInfo struct { | ||||
| JobFileInfoBase | |||||
| Type string `json:"type" union:"Image"` | Type string `json:"type" union:"Image"` | ||||
| ImageID string `json:"imageID"` | ImageID string `json:"imageID"` | ||||
| } | } | ||||
| @@ -16,16 +16,15 @@ const ( | |||||
| ) | ) | ||||
| type SlwNode struct { | type SlwNode struct { | ||||
| ID int64 `json:"ID"` | |||||
| Name string `json:"name"` | |||||
| SlwRegionID int64 `json:"slwRegionID"` | |||||
| StgNodeID int64 `json:"stgNodeID"` | |||||
| StorageID int64 `json:"StorageID"` | |||||
| ID int64 `json:"ID"` | |||||
| Name string `json:"name"` | |||||
| SlwRegionID int64 `json:"slwRegionID"` | |||||
| StgNodeID int64 `json:"stgNodeID"` | |||||
| StorageID int64 `json:"StorageID"` | |||||
| } | } | ||||
| type ResourceData interface{} | |||||
| type ResourceDataConst interface { | |||||
| ResourceData | CPUResourceData | NPUResourceData | GPUResourceData | MLUResourceData | StorageResourceData | MemoryResourceData | |||||
| type ResourceData interface { | |||||
| Noop() | |||||
| } | } | ||||
| var ResourceDataTypeUnion = types.NewTypeUnion[ResourceData]( | var ResourceDataTypeUnion = types.NewTypeUnion[ResourceData]( | ||||
| @@ -38,19 +37,24 @@ var ResourceDataTypeUnion = types.NewTypeUnion[ResourceData]( | |||||
| ) | ) | ||||
| var ResourceDataTaggedTypeUnion = serder.NewTaggedTypeUnion(ResourceDataTypeUnion, "Name", "name") | var ResourceDataTaggedTypeUnion = serder.NewTaggedTypeUnion(ResourceDataTypeUnion, "Name", "name") | ||||
| type ResourceDataBase struct{} | |||||
| func (d *ResourceDataBase) Noop() {} | |||||
| type DetailType[T any] struct { | type DetailType[T any] struct { | ||||
| Unit string `json:"unit"` | Unit string `json:"unit"` | ||||
| Value T `json:"value"` | Value T `json:"value"` | ||||
| } | } | ||||
| type CPUResourceData struct { | type CPUResourceData struct { | ||||
| ResourceDataBase | |||||
| Name string `json:"name" union:"CPU"` | Name string `json:"name" union:"CPU"` | ||||
| Total DetailType[int64] `json:"total"` | Total DetailType[int64] `json:"total"` | ||||
| Available DetailType[int64] `json:"available"` | Available DetailType[int64] `json:"available"` | ||||
| } | } | ||||
| func NewCPUResourceData(name string, total DetailType[int64], available DetailType[int64]) CPUResourceData { | |||||
| return CPUResourceData{ | |||||
| func NewCPUResourceData(name string, total DetailType[int64], available DetailType[int64]) *CPUResourceData { | |||||
| return &CPUResourceData{ | |||||
| Name: name, | Name: name, | ||||
| Total: total, | Total: total, | ||||
| Available: available, | Available: available, | ||||
| @@ -58,13 +62,14 @@ func NewCPUResourceData(name string, total DetailType[int64], available DetailTy | |||||
| } | } | ||||
| type NPUResourceData struct { | type NPUResourceData struct { | ||||
| ResourceDataBase | |||||
| Name string `json:"name" union:"NPU"` | Name string `json:"name" union:"NPU"` | ||||
| Total DetailType[int64] `json:"total"` | Total DetailType[int64] `json:"total"` | ||||
| Available DetailType[int64] `json:"available"` | Available DetailType[int64] `json:"available"` | ||||
| } | } | ||||
| func NewNPUResourceData(name string, total DetailType[int64], available DetailType[int64]) NPUResourceData { | |||||
| return NPUResourceData{ | |||||
| func NewNPUResourceData(name string, total DetailType[int64], available DetailType[int64]) *NPUResourceData { | |||||
| return &NPUResourceData{ | |||||
| Name: name, | Name: name, | ||||
| Total: total, | Total: total, | ||||
| Available: available, | Available: available, | ||||
| @@ -72,13 +77,14 @@ func NewNPUResourceData(name string, total DetailType[int64], available DetailTy | |||||
| } | } | ||||
| type GPUResourceData struct { | type GPUResourceData struct { | ||||
| ResourceDataBase | |||||
| Name string `json:"name" union:"GPU"` | Name string `json:"name" union:"GPU"` | ||||
| Total DetailType[int64] `json:"total"` | Total DetailType[int64] `json:"total"` | ||||
| Available DetailType[int64] `json:"available"` | Available DetailType[int64] `json:"available"` | ||||
| } | } | ||||
| func NewGPUResourceData(name string, total DetailType[int64], available DetailType[int64]) GPUResourceData { | |||||
| return GPUResourceData{ | |||||
| func NewGPUResourceData(name string, total DetailType[int64], available DetailType[int64]) *GPUResourceData { | |||||
| return &GPUResourceData{ | |||||
| Name: name, | Name: name, | ||||
| Total: total, | Total: total, | ||||
| Available: available, | Available: available, | ||||
| @@ -86,13 +92,14 @@ func NewGPUResourceData(name string, total DetailType[int64], available DetailTy | |||||
| } | } | ||||
| type MLUResourceData struct { | type MLUResourceData struct { | ||||
| ResourceDataBase | |||||
| Name string `json:"name" union:"MLU"` | Name string `json:"name" union:"MLU"` | ||||
| Total DetailType[int64] `json:"total"` | Total DetailType[int64] `json:"total"` | ||||
| Available DetailType[int64] `json:"available"` | Available DetailType[int64] `json:"available"` | ||||
| } | } | ||||
| func NewMLUResourceData(name string, total DetailType[int64], available DetailType[int64]) MLUResourceData { | |||||
| return MLUResourceData{ | |||||
| func NewMLUResourceData(name string, total DetailType[int64], available DetailType[int64]) *MLUResourceData { | |||||
| return &MLUResourceData{ | |||||
| Name: name, | Name: name, | ||||
| Total: total, | Total: total, | ||||
| Available: available, | Available: available, | ||||
| @@ -100,13 +107,14 @@ func NewMLUResourceData(name string, total DetailType[int64], available DetailTy | |||||
| } | } | ||||
| type StorageResourceData struct { | type StorageResourceData struct { | ||||
| ResourceDataBase | |||||
| Name string `json:"name" union:"STORAGE"` | Name string `json:"name" union:"STORAGE"` | ||||
| Total DetailType[float64] `json:"total"` | Total DetailType[float64] `json:"total"` | ||||
| Available DetailType[float64] `json:"available"` | Available DetailType[float64] `json:"available"` | ||||
| } | } | ||||
| func NewStorageResourceData(name string, total DetailType[float64], available DetailType[float64]) StorageResourceData { | |||||
| return StorageResourceData{ | |||||
| func NewStorageResourceData(name string, total DetailType[float64], available DetailType[float64]) *StorageResourceData { | |||||
| return &StorageResourceData{ | |||||
| Name: name, | Name: name, | ||||
| Total: total, | Total: total, | ||||
| Available: available, | Available: available, | ||||
| @@ -114,13 +122,14 @@ func NewStorageResourceData(name string, total DetailType[float64], available De | |||||
| } | } | ||||
| type MemoryResourceData struct { | type MemoryResourceData struct { | ||||
| ResourceDataBase | |||||
| Name string `json:"name" union:"MEMORY"` | Name string `json:"name" union:"MEMORY"` | ||||
| Total DetailType[float64] `json:"total"` | Total DetailType[float64] `json:"total"` | ||||
| Available DetailType[float64] `json:"available"` | Available DetailType[float64] `json:"available"` | ||||
| } | } | ||||
| func NewMemoryResourceData(name string, total DetailType[float64], available DetailType[float64]) MemoryResourceData { | |||||
| return MemoryResourceData{ | |||||
| func NewMemoryResourceData(name string, total DetailType[float64], available DetailType[float64]) *MemoryResourceData { | |||||
| return &MemoryResourceData{ | |||||
| Name: name, | Name: name, | ||||
| Total: total, | Total: total, | ||||
| Available: available, | Available: available, | ||||
| @@ -20,16 +20,16 @@ const ( | |||||
| type MessageBody interface { | type MessageBody interface { | ||||
| // 此方法无任何作用,仅用于避免MessageBody是一个空interface,从而导致任何类型的值都可以赋值给它 | // 此方法无任何作用,仅用于避免MessageBody是一个空interface,从而导致任何类型的值都可以赋值给它 | ||||
| // 与下方的MessageBodyBase配合使用: | // 与下方的MessageBodyBase配合使用: | ||||
| // IsMessageBody只让实现了此接口的类型能赋值给它,内嵌MessageBodyBase让类型必须是个指针类型, | |||||
| // Noop只让实现了此接口的类型能赋值给它,内嵌MessageBodyBase让类型必须是个指针类型, | |||||
| // 这就确保了Message.Body必是某个类型的指针类型,避免序列化、反序列化过程出错 | // 这就确保了Message.Body必是某个类型的指针类型,避免序列化、反序列化过程出错 | ||||
| IsMessageBody() | |||||
| Noop() | |||||
| } | } | ||||
| // 这个结构体无任何字段,但实现了IsMessageBody,每种MessageBody都要内嵌这个结构体 | |||||
| // 这个结构体无任何字段,但实现了Noop,每种MessageBody都要内嵌这个结构体 | |||||
| type MessageBodyBase struct{} | type MessageBodyBase struct{} | ||||
| // 此处的receiver是指针 | // 此处的receiver是指针 | ||||
| func (b *MessageBodyBase) IsMessageBody() {} | |||||
| func (b *MessageBodyBase) Noop() {} | |||||
| type Message struct { | type Message struct { | ||||
| Type string `json:"type"` | Type string `json:"type"` | ||||
| @@ -4,8 +4,11 @@ import ( | |||||
| myreflect "gitlink.org.cn/cloudream/common/utils/reflect" | myreflect "gitlink.org.cn/cloudream/common/utils/reflect" | ||||
| ) | ) | ||||
| // 描述一个类型集合 | |||||
| type TypeUnion struct { | type TypeUnion struct { | ||||
| UnionType myreflect.Type | |||||
| // 这个集合的类型 | |||||
| UnionType myreflect.Type | |||||
| // 集合中包含的类型,即遇到UnionType类型的值时,它内部的实际类型的范围 | |||||
| ElementTypes []myreflect.Type | ElementTypes []myreflect.Type | ||||
| } | } | ||||
| @@ -108,7 +108,8 @@ func MapToObject(m map[string]any, obj any, opt ...MapToObjectOption) error { | |||||
| convs := []Converter{ | convs := []Converter{ | ||||
| func(from reflect.Value, to reflect.Value) (interface{}, error) { | func(from reflect.Value, to reflect.Value) (interface{}, error) { | ||||
| info, ok := unionTypeMapping[to.Type()] | |||||
| toType := to.Type() | |||||
| info, ok := unionTypeMapping[toType] | |||||
| if !ok { | if !ok { | ||||
| return from.Interface(), nil | return from.Interface(), nil | ||||
| } | } | ||||
| @@ -116,20 +117,20 @@ func MapToObject(m map[string]any, obj any, opt ...MapToObjectOption) error { | |||||
| mp := from.Interface().(map[string]any) | mp := from.Interface().(map[string]any) | ||||
| tag, ok := mp[info.JSONTagField] | tag, ok := mp[info.JSONTagField] | ||||
| if !ok { | if !ok { | ||||
| return nil, fmt.Errorf("converting to %v: no tag field %s in map", to.Type(), info.JSONTagField) | |||||
| return nil, fmt.Errorf("converting to %v: no tag field %s in map", toType, info.JSONTagField) | |||||
| } | } | ||||
| tagStr, ok := tag.(string) | tagStr, ok := tag.(string) | ||||
| if !ok { | if !ok { | ||||
| return nil, fmt.Errorf("converting to %v: tag field %s value is %v, which is not a string", to.Type(), info.JSONTagField, tag) | |||||
| return nil, fmt.Errorf("converting to %v: tag field %s value is %v, which is not a string", toType, info.JSONTagField, tag) | |||||
| } | } | ||||
| eleType, ok := info.TagToType[tagStr] | eleType, ok := info.TagToType[tagStr] | ||||
| if !ok { | if !ok { | ||||
| return nil, fmt.Errorf("converting to %v: unknow type tag %s", to.Type(), tagStr) | |||||
| return nil, fmt.Errorf("converting to %v: unknow type tag %s", toType, tagStr) | |||||
| } | } | ||||
| to.Set(reflect.Indirect(reflect.New(eleType))) | |||||
| to.Set(reflect.New(eleType)) | |||||
| return from.Interface(), nil | return from.Interface(), nil | ||||
| }, | }, | ||||
| @@ -404,8 +404,8 @@ func Test_MapToObject(t *testing.T) { | |||||
| So(err, ShouldBeNil) | So(err, ShouldBeNil) | ||||
| So(ret.Us, ShouldResemble, []UnionType{ | So(ret.Us, ShouldResemble, []UnionType{ | ||||
| EleType1{Type: "1", Value1: "1"}, | |||||
| EleType2{Type: "2", Value2: 2}, | |||||
| &EleType1{Type: "1", Value1: "1"}, | |||||
| &EleType2{Type: "2", Value2: 2}, | |||||
| }) | }) | ||||
| }) | }) | ||||
| @@ -442,6 +442,6 @@ func Test_MapToObject(t *testing.T) { | |||||
| So(err, ShouldBeNil) | So(err, ShouldBeNil) | ||||
| So(ret, ShouldResemble, EleType1{Type: "1", Value1: "1"}) | |||||
| So(ret, ShouldResemble, &EleType1{Type: "1", Value1: "1"}) | |||||
| }) | }) | ||||
| } | } | ||||