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{
JobSetInfo: models.JobSetInfo{
Jobs: []models.JobInfo{
models.ResourceJobInfo{
&models.ResourceJobInfo{
Type: models.JobTypeResource,
},
models.NormalJobInfo{
&models.NormalJobInfo{
Type: models.JobTypeNormal,
Files: models.JobFilesInfo{
Dataset: models.PackageJobFileInfo{
Dataset: &models.PackageJobFileInfo{
Type: models.FileInfoTypePackage,
},
Code: models.LocalJobFileInfo{
Code: &models.LocalJobFileInfo{
Type: models.FileInfoTypeLocalFile,
LocalPath: "code",
},
Image: models.ImageJobFileInfo{
Image: &models.ImageJobFileInfo{
Type: models.FileInfoTypeImage,
},
},


+ 28
- 8
models/scheduler.go View File

@@ -20,7 +20,9 @@ type JobSetInfo struct {
Jobs []JobInfo `json:"jobs"`
}

type JobInfo interface{}
type JobInfo interface {
GetLocalJobID() string
}

var JobInfoTypeUnion = types.NewTypeUnion[JobInfo](
myreflect.TypeOf[NormalJobInfo](),
@@ -28,16 +30,24 @@ var JobInfoTypeUnion = types.NewTypeUnion[JobInfo](
)
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 {
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 {
LocalJobID string `json:"localJobID"`
JobInfoBase
Type string `json:"type" union:"Resource"`
TargetLocalJobID string `json:"targetLocalJobID"`
}
@@ -48,7 +58,9 @@ type JobFilesInfo struct {
Image JobFileInfo `json:"image"`
}

type JobFileInfo interface{}
type JobFileInfo interface {
Noop()
}

var FileInfoTypeUnion = types.NewTypeUnion[JobFileInfo](
myreflect.TypeOf[PackageJobFileInfo](),
@@ -58,22 +70,30 @@ var FileInfoTypeUnion = types.NewTypeUnion[JobFileInfo](
)
var FileInfoTaggedTypeUnion = serder.NewTaggedTypeUnion(FileInfoTypeUnion, "Type", "type")

type JobFileInfoBase struct{}

func (i *JobFileInfoBase) Noop() {}

type PackageJobFileInfo struct {
JobFileInfoBase
Type string `json:"type" union:"Package"`
PackageID int64 `json:"packageID"`
}

type LocalJobFileInfo struct {
JobFileInfoBase
Type string `json:"type" union:"LocalFile"`
LocalPath string `json:"localPath"`
}

type ResourceJobFileInfo struct {
JobFileInfoBase
Type string `json:"type" union:"Resource"`
ResourceLocalJobID string `json:"resourceLocalJobID"`
}

type ImageJobFileInfo struct {
JobFileInfoBase
Type string `json:"type" union:"Image"`
ImageID string `json:"imageID"`
}


+ 29
- 20
models/unifyops.go View File

@@ -16,16 +16,15 @@ const (
)

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](
@@ -38,19 +37,24 @@ var ResourceDataTypeUnion = types.NewTypeUnion[ResourceData](
)
var ResourceDataTaggedTypeUnion = serder.NewTaggedTypeUnion(ResourceDataTypeUnion, "Name", "name")

type ResourceDataBase struct{}

func (d *ResourceDataBase) Noop() {}

type DetailType[T any] struct {
Unit string `json:"unit"`
Value T `json:"value"`
}

type CPUResourceData struct {
ResourceDataBase
Name string `json:"name" union:"CPU"`
Total DetailType[int64] `json:"total"`
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,
Total: total,
Available: available,
@@ -58,13 +62,14 @@ func NewCPUResourceData(name string, total DetailType[int64], available DetailTy
}

type NPUResourceData struct {
ResourceDataBase
Name string `json:"name" union:"NPU"`
Total DetailType[int64] `json:"total"`
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,
Total: total,
Available: available,
@@ -72,13 +77,14 @@ func NewNPUResourceData(name string, total DetailType[int64], available DetailTy
}

type GPUResourceData struct {
ResourceDataBase
Name string `json:"name" union:"GPU"`
Total DetailType[int64] `json:"total"`
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,
Total: total,
Available: available,
@@ -86,13 +92,14 @@ func NewGPUResourceData(name string, total DetailType[int64], available DetailTy
}

type MLUResourceData struct {
ResourceDataBase
Name string `json:"name" union:"MLU"`
Total DetailType[int64] `json:"total"`
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,
Total: total,
Available: available,
@@ -100,13 +107,14 @@ func NewMLUResourceData(name string, total DetailType[int64], available DetailTy
}

type StorageResourceData struct {
ResourceDataBase
Name string `json:"name" union:"STORAGE"`
Total DetailType[float64] `json:"total"`
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,
Total: total,
Available: available,
@@ -114,13 +122,14 @@ func NewStorageResourceData(name string, total DetailType[float64], available De
}

type MemoryResourceData struct {
ResourceDataBase
Name string `json:"name" union:"MEMORY"`
Total DetailType[float64] `json:"total"`
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,
Total: total,
Available: available,


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

@@ -20,16 +20,16 @@ const (
type MessageBody interface {
// 此方法无任何作用,仅用于避免MessageBody是一个空interface,从而导致任何类型的值都可以赋值给它
// 与下方的MessageBodyBase配合使用:
// IsMessageBody只让实现了此接口的类型能赋值给它,内嵌MessageBodyBase让类型必须是个指针类型,
// Noop只让实现了此接口的类型能赋值给它,内嵌MessageBodyBase让类型必须是个指针类型,
// 这就确保了Message.Body必是某个类型的指针类型,避免序列化、反序列化过程出错
IsMessageBody()
Noop()
}

// 这个结构体无任何字段,但实现了IsMessageBody,每种MessageBody都要内嵌这个结构体
// 这个结构体无任何字段,但实现了Noop,每种MessageBody都要内嵌这个结构体
type MessageBodyBase struct{}

// 此处的receiver是指针
func (b *MessageBodyBase) IsMessageBody() {}
func (b *MessageBodyBase) Noop() {}

type Message struct {
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"
)

// 描述一个类型集合
type TypeUnion struct {
UnionType myreflect.Type
// 这个集合的类型
UnionType myreflect.Type
// 集合中包含的类型,即遇到UnionType类型的值时,它内部的实际类型的范围
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{
func(from reflect.Value, to reflect.Value) (interface{}, error) {
info, ok := unionTypeMapping[to.Type()]
toType := to.Type()
info, ok := unionTypeMapping[toType]
if !ok {
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)
tag, ok := mp[info.JSONTagField]
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)
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]
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
},


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

@@ -404,8 +404,8 @@ func Test_MapToObject(t *testing.T) {
So(err, ShouldBeNil)

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(ret, ShouldResemble, EleType1{Type: "1", Value1: "1"})
So(ret, ShouldResemble, &EleType1{Type: "1", Value1: "1"})
})
}

Loading…
Cancel
Save