mirror of
https://github.com/aceld/kis-flow.git
synced 2025-01-23 07:30:23 +08:00
155 lines
4.7 KiB
Go
155 lines
4.7 KiB
Go
package kis
|
||
|
||
import (
|
||
"errors"
|
||
"fmt"
|
||
"reflect"
|
||
"runtime"
|
||
"strings"
|
||
)
|
||
|
||
// FaaS Function as a Service
|
||
|
||
// 将
|
||
// type FaaS func(context.Context, Flow) error
|
||
// 改为
|
||
// type FaaS func(context.Context, Flow, ...interface{}) error
|
||
// 可以通过可变参数的任意输入类型进行数据传递
|
||
type FaaS interface{}
|
||
|
||
// FaaSDesc FaaS 回调计算业务函数 描述
|
||
type FaaSDesc struct {
|
||
Serialize // 当前Function的数据输入输出序列化实现
|
||
FnName string // Function名称
|
||
f interface{} // FaaS 函数
|
||
fName string // 函数名称
|
||
ArgsType []reflect.Type // 函数参数类型(集合)
|
||
ArgNum int // 函数参数个数
|
||
FuncType reflect.Type // 函数类型
|
||
FuncValue reflect.Value // 函数值(函数地址)
|
||
}
|
||
|
||
// NewFaaSDesc 根据用户注册的FnName 和FaaS 回调函数,创建 FaaSDesc 描述实例
|
||
func NewFaaSDesc(fnName string, f FaaS) (*FaaSDesc, error) {
|
||
|
||
// 输入输出序列化实例
|
||
var serializeImpl Serialize
|
||
|
||
// 传入的回调函数FaaS,函数值(函数地址)
|
||
funcValue := reflect.ValueOf(f)
|
||
|
||
// 传入的回调函数FaaS 类型
|
||
funcType := funcValue.Type()
|
||
|
||
// 判断传递的FaaS指针是否是函数类型
|
||
if !isFuncType(funcType) {
|
||
return nil, fmt.Errorf("provided FaaS type is %s, not a function", funcType.Name())
|
||
}
|
||
|
||
// 判断传递的FaaS函数是否有返回值类型是只包括(error)
|
||
if funcType.NumOut() != 1 || funcType.Out(0) != reflect.TypeOf((*error)(nil)).Elem() {
|
||
return nil, errors.New("function must have exactly one return value of type error")
|
||
}
|
||
|
||
// FaaS函数的参数类型集合
|
||
argsType := make([]reflect.Type, funcType.NumIn())
|
||
|
||
// 获取FaaS的函数名称
|
||
fullName := runtime.FuncForPC(funcValue.Pointer()).Name()
|
||
|
||
// 确保 FaaS func(context.Context, Flow, ...interface{}) error 形参列表,存在context.Context 和 kis.Flow
|
||
|
||
// 是否包含kis.Flow类型的形参
|
||
containsKisFlow := false
|
||
// 是否包含context.Context类型的形参
|
||
containsCtx := false
|
||
|
||
// 遍历FaaS的形参类型
|
||
for i := 0; i < funcType.NumIn(); i++ {
|
||
|
||
// 取出第i个形式参数类型
|
||
paramType := funcType.In(i)
|
||
|
||
if isFlowType(paramType) {
|
||
// 判断是否包含kis.Flow类型的形参
|
||
containsKisFlow = true
|
||
|
||
} else if isContextType(paramType) {
|
||
// 判断是否包含context.Context类型的形参
|
||
containsCtx = true
|
||
|
||
} else if isSliceType(paramType) {
|
||
|
||
// 获取当前参数Slice的元素类型
|
||
itemType := paramType.Elem()
|
||
|
||
// 如果当前参数是一个指针类型,则获取指针指向的结构体类型
|
||
if itemType.Kind() == reflect.Ptr {
|
||
itemType = itemType.Elem() // 获取指针指向的结构体类型
|
||
}
|
||
|
||
// Check if f implements Serialize interface
|
||
// (检测传递的FaaS函数是否实现了Serialize接口)
|
||
if isSerialize(itemType) {
|
||
// 如果当前形参实现了Serialize接口,则使用当前形参的序列化实现
|
||
serializeImpl = reflect.New(itemType).Interface().(Serialize)
|
||
|
||
} else {
|
||
// 如果当前形参没有实现Serialize接口,则使用默认的序列化实现
|
||
serializeImpl = defaultSerialize // Use global default implementation
|
||
}
|
||
} else {
|
||
// Other types are not supported
|
||
}
|
||
|
||
// 将当前形参类型追加到argsType集合中
|
||
argsType[i] = paramType
|
||
}
|
||
|
||
if !containsKisFlow {
|
||
// 不包含kis.Flow类型的形参,返回错误
|
||
return nil, errors.New("function parameters must have kis.Flow param, please use FaaS type like: [type FaaS func(context.Context, Flow, ...interface{}) error]")
|
||
}
|
||
|
||
if !containsCtx {
|
||
// 不包含context.Context类型的形参,返回错误
|
||
return nil, errors.New("function parameters must have context, please use FaaS type like: [type FaaS func(context.Context, Flow, ...interface{}) error]")
|
||
}
|
||
|
||
// 返回FaaSDesc描述实例
|
||
return &FaaSDesc{
|
||
Serialize: serializeImpl,
|
||
FnName: fnName,
|
||
f: f,
|
||
fName: fullName,
|
||
ArgsType: argsType,
|
||
ArgNum: len(argsType),
|
||
FuncType: funcType,
|
||
FuncValue: funcValue,
|
||
}, nil
|
||
}
|
||
|
||
// isFuncType 判断传递进来的 paramType 是否是函数类型
|
||
func isFuncType(paramType reflect.Type) bool {
|
||
return paramType.Kind() == reflect.Func
|
||
}
|
||
|
||
// isFlowType 判断传递进来的 paramType 是否是 kis.Flow 类型
|
||
func isFlowType(paramType reflect.Type) bool {
|
||
var flowInterfaceType = reflect.TypeOf((*Flow)(nil)).Elem()
|
||
|
||
return paramType.Implements(flowInterfaceType)
|
||
}
|
||
|
||
// isContextType 判断传递进来的 paramType 是否是 context.Context 类型
|
||
func isContextType(paramType reflect.Type) bool {
|
||
typeName := paramType.Name()
|
||
|
||
return strings.Contains(typeName, "Context")
|
||
}
|
||
|
||
// isSliceType 判断传递进来的 paramType 是否是切片类型
|
||
func isSliceType(paramType reflect.Type) bool {
|
||
return paramType.Kind() == reflect.Slice
|
||
}
|