2024-03-19 19:16:03 +08:00
package kis
import (
"errors"
"fmt"
"reflect"
"runtime"
2024-03-25 16:35:20 +08:00
"strings"
2024-03-19 19:16:03 +08:00
)
// FaaS Function as a Service
2024-03-25 16:35:20 +08:00
// 将
// type FaaS func(context.Context, Flow) error
// 改为
// type FaaS func(context.Context, Flow, ...interface{}) error
// 可以通过可变参数的任意输入类型进行数据传递
2024-03-19 19:16:03 +08:00
type FaaS interface { }
2024-03-25 16:35:20 +08:00
// FaaSDesc FaaS 回调计算业务函数 描述
2024-03-19 19:16:03 +08:00
type FaaSDesc struct {
2024-03-25 16:35:20 +08:00
Serialize // 当前Function的数据输入输出序列化实现
FnName string // Function名称
f interface { } // FaaS 函数
fName string // 函数名称
ArgsType [ ] reflect . Type // 函数参数类型(集合)
ArgNum int // 函数参数个数
FuncType reflect . Type // 函数类型
FuncValue reflect . Value // 函数值(函数地址)
2024-03-19 19:16:03 +08:00
}
2024-03-25 16:35:20 +08:00
// NewFaaSDesc 根据用户注册的FnName 和FaaS 回调函数,创建 FaaSDesc 描述实例
2024-03-19 19:16:03 +08:00
func NewFaaSDesc ( fnName string , f FaaS ) ( * FaaSDesc , error ) {
2024-03-21 10:13:32 +08:00
2024-03-25 16:35:20 +08:00
// 输入输出序列化实例
var serializeImpl Serialize
2024-03-21 10:13:32 +08:00
2024-03-25 16:35:20 +08:00
// 传入的回调函数FaaS,函数值(函数地址)
2024-03-19 19:16:03 +08:00
funcValue := reflect . ValueOf ( f )
2024-03-25 16:35:20 +08:00
// 传入的回调函数FaaS 类型
2024-03-19 19:16:03 +08:00
funcType := funcValue . Type ( )
2024-03-25 16:35:20 +08:00
// 判断传递的FaaS指针是否是函数类型
if ! isFuncType ( funcType ) {
return nil , fmt . Errorf ( "provided FaaS type is %s, not a function" , funcType . Name ( ) )
2024-03-19 19:16:03 +08:00
}
2024-03-25 16:35:20 +08:00
// 判断传递的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函数的参数类型集合
2024-03-19 19:16:03 +08:00
argsType := make ( [ ] reflect . Type , funcType . NumIn ( ) )
2024-03-25 16:35:20 +08:00
// 获取FaaS的函数名称
2024-03-19 19:16:03 +08:00
fullName := runtime . FuncForPC ( funcValue . Pointer ( ) ) . Name ( )
2024-03-25 16:35:20 +08:00
// 确保 FaaS func(context.Context, Flow, ...interface{}) error 形参列表, 存在context.Context 和 kis.Flow
// 是否包含kis.Flow类型的形参
2024-03-21 10:13:32 +08:00
containsKisFlow := false
2024-03-25 16:35:20 +08:00
// 是否包含context.Context类型的形参
2024-03-21 10:13:32 +08:00
containsCtx := false
2024-03-19 19:16:03 +08:00
2024-03-25 16:35:20 +08:00
// 遍历FaaS的形参类型
2024-03-19 19:16:03 +08:00
for i := 0 ; i < funcType . NumIn ( ) ; i ++ {
2024-03-25 16:35:20 +08:00
// 取出第i个形式参数类型
2024-03-19 19:16:03 +08:00
paramType := funcType . In ( i )
2024-03-25 16:35:20 +08:00
2024-03-19 19:16:03 +08:00
if isFlowType ( paramType ) {
2024-03-25 16:35:20 +08:00
// 判断是否包含kis.Flow类型的形参
2024-03-21 10:13:32 +08:00
containsKisFlow = true
2024-03-25 16:35:20 +08:00
2024-03-21 10:13:32 +08:00
} else if isContextType ( paramType ) {
2024-03-25 16:35:20 +08:00
// 判断是否包含context.Context类型的形参
2024-03-21 10:13:32 +08:00
containsCtx = true
2024-03-25 16:35:20 +08:00
} else if isSliceType ( paramType ) {
// 获取当前参数Slice的元素类型
2024-03-21 10:13:32 +08:00
itemType := paramType . Elem ( )
2024-03-25 16:35:20 +08:00
// 如果当前参数是一个指针类型,则获取指针指向的结构体类型
2024-03-21 10:13:32 +08:00
if itemType . Kind ( ) == reflect . Ptr {
2024-03-25 16:35:20 +08:00
itemType = itemType . Elem ( ) // 获取指针指向的结构体类型
2024-03-21 10:13:32 +08:00
}
2024-03-25 16:35:20 +08:00
// Check if f implements Serialize interface
// (检测传递的FaaS函数是否实现了Serialize接口)
if isSerialize ( itemType ) {
// 如果当前形参实现了Serialize接口, 则使用当前形参的序列化实现
serializeImpl = reflect . New ( itemType ) . Interface ( ) . ( Serialize )
2024-03-21 10:13:32 +08:00
} else {
2024-03-25 16:35:20 +08:00
// 如果当前形参没有实现Serialize接口, 则使用默认的序列化实现
serializeImpl = defaultSerialize // Use global default implementation
2024-03-21 10:13:32 +08:00
}
2024-03-25 16:35:20 +08:00
} else {
// Other types are not supported
2024-03-19 19:16:03 +08:00
}
2024-03-25 16:35:20 +08:00
// 将当前形参类型追加到argsType集合中
2024-03-19 19:16:03 +08:00
argsType [ i ] = paramType
}
2024-03-21 10:13:32 +08:00
if ! containsKisFlow {
2024-03-25 16:35:20 +08:00
// 不包含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]" )
2024-03-21 10:13:32 +08:00
}
2024-03-19 19:16:03 +08:00
2024-03-25 16:35:20 +08:00
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]" )
2024-03-19 19:16:03 +08:00
}
2024-03-25 16:35:20 +08:00
// 返回FaaSDesc描述实例
2024-03-19 19:16:03 +08:00
return & FaaSDesc {
2024-03-25 16:35:20 +08:00
Serialize : serializeImpl ,
FnName : fnName ,
f : f ,
fName : fullName ,
ArgsType : argsType ,
ArgNum : len ( argsType ) ,
FuncType : funcType ,
FuncValue : funcValue ,
2024-03-19 19:16:03 +08:00
} , nil
}
2024-03-25 16:35:20 +08:00
// 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
2024-03-19 19:16:03 +08:00
}