Browse Source

支持在UnionType(一个interface)上声明方法

pull/21/head
Sydonian 2 years ago
parent
commit
cb17dfc40b
7 changed files with 79 additions and 46 deletions
  1. +5
    -5
      api/scheduler/scheduler_test.go
  2. +28
    -8
      models/scheduler.go
  3. +29
    -20
      models/unifyops.go
  4. +4
    -4
      pkgs/mq/message.go
  5. +4
    -1
      pkgs/types/union.go
  6. +6
    -5
      utils/serder/serder.go
  7. +3
    -3
      utils/serder/serder_test.go

+ 5
- 5
api/scheduler/scheduler_test.go View File

@@ -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,
}, },
}, },


+ 28
- 8
models/scheduler.go View File

@@ -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"`
} }


+ 29
- 20
models/unifyops.go View File

@@ -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,


+ 4
- 4
pkgs/mq/message.go View File

@@ -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
- 1
pkgs/types/union.go View File

@@ -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
} }




+ 6
- 5
utils/serder/serder.go View File

@@ -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
}, },


+ 3
- 3
utils/serder/serder_test.go View File

@@ -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"})
}) })
} }

Loading…
Cancel
Save