2023-12-31 18:04:28 +08:00
|
|
|
|
package flow
|
|
|
|
|
|
2024-01-01 17:49:27 +08:00
|
|
|
|
import (
|
|
|
|
|
"context"
|
|
|
|
|
"errors"
|
2024-03-26 14:54:50 +08:00
|
|
|
|
"github.com/aceld/kis-flow/common"
|
|
|
|
|
"github.com/aceld/kis-flow/config"
|
|
|
|
|
"github.com/aceld/kis-flow/conn"
|
|
|
|
|
"github.com/aceld/kis-flow/function"
|
|
|
|
|
"github.com/aceld/kis-flow/id"
|
|
|
|
|
"github.com/aceld/kis-flow/kis"
|
|
|
|
|
"github.com/aceld/kis-flow/log"
|
|
|
|
|
"github.com/aceld/kis-flow/metrics"
|
2024-03-18 09:29:05 +08:00
|
|
|
|
"github.com/prometheus/client_golang/prometheus"
|
2024-01-01 17:49:27 +08:00
|
|
|
|
"sync"
|
2024-01-26 17:27:29 +08:00
|
|
|
|
"time"
|
2024-03-01 16:29:07 +08:00
|
|
|
|
|
|
|
|
|
"github.com/patrickmn/go-cache"
|
2024-01-01 17:49:27 +08:00
|
|
|
|
)
|
2023-12-31 18:04:28 +08:00
|
|
|
|
|
|
|
|
|
// KisFlow 用于贯穿整条流式计算的上下文环境
|
|
|
|
|
type KisFlow struct {
|
2024-01-01 17:49:27 +08:00
|
|
|
|
// 基础信息
|
2024-01-03 10:16:54 +08:00
|
|
|
|
Id string // Flow的分布式实例ID(用于KisFlow内部区分不同实例)
|
2024-01-01 17:49:27 +08:00
|
|
|
|
Name string // Flow的可读名称
|
|
|
|
|
Conf *config.KisFlowConfig // Flow配置策略
|
|
|
|
|
|
|
|
|
|
// Function列表
|
2024-01-12 17:27:43 +08:00
|
|
|
|
Funcs map[string]kis.Function // 当前flow拥有的全部管理的全部Function对象, key: FunctionName
|
2024-01-01 17:49:27 +08:00
|
|
|
|
FlowHead kis.Function // 当前Flow所拥有的Function列表表头
|
|
|
|
|
FlowTail kis.Function // 当前Flow所拥有的Function列表表尾
|
|
|
|
|
flock sync.RWMutex // 管理链表插入读写的锁
|
|
|
|
|
ThisFunction kis.Function // Flow当前正在执行的KisFunction对象
|
2024-01-12 17:27:43 +08:00
|
|
|
|
ThisFunctionId string // 当前执行到的Function ID
|
|
|
|
|
PrevFunctionId string // 当前执行到的Function 上一层FunctionID
|
2024-01-01 17:49:27 +08:00
|
|
|
|
|
|
|
|
|
// Function列表参数
|
2024-01-03 17:22:35 +08:00
|
|
|
|
funcParams map[string]config.FParam // flow在当前Function的自定义固定配置参数,Key:function的实例KisID, value:FParam
|
2024-01-01 17:49:27 +08:00
|
|
|
|
fplock sync.RWMutex // 管理funcParams的读写锁
|
2024-01-03 17:22:35 +08:00
|
|
|
|
|
|
|
|
|
// 数据
|
|
|
|
|
buffer common.KisRowArr // 用来临时存放输入字节数据的内部Buf, 一条数据为interface{}, 多条数据为[]interface{} 也就是KisBatch
|
|
|
|
|
data common.KisDataMap // 流式计算各个层级的数据源
|
|
|
|
|
inPut common.KisRowArr // 当前Function的计算输入数据
|
2024-01-23 16:21:02 +08:00
|
|
|
|
abort bool // 是否中断Flow
|
|
|
|
|
action kis.Action // 当前Flow所携带的Action动作
|
2024-01-26 17:27:29 +08:00
|
|
|
|
|
|
|
|
|
// flow的本地缓存
|
|
|
|
|
cache *cache.Cache // Flow流的临时缓存上线文环境
|
|
|
|
|
|
|
|
|
|
// flow的metaData
|
|
|
|
|
metaData map[string]interface{} // Flow的自定义临时数据
|
|
|
|
|
mLock sync.RWMutex // 管理metaData的读写锁
|
2023-12-31 18:04:28 +08:00
|
|
|
|
}
|
|
|
|
|
|
2024-01-01 17:49:27 +08:00
|
|
|
|
// NewKisFlow 创建一个KisFlow.
|
|
|
|
|
func NewKisFlow(conf *config.KisFlowConfig) kis.Flow {
|
2023-12-31 18:04:28 +08:00
|
|
|
|
flow := new(KisFlow)
|
2024-01-03 10:16:54 +08:00
|
|
|
|
// 实例Id
|
|
|
|
|
flow.Id = id.KisID(common.KisIdTypeFlow)
|
2024-01-01 17:49:27 +08:00
|
|
|
|
|
|
|
|
|
// 基础信息
|
|
|
|
|
flow.Name = conf.FlowName
|
|
|
|
|
flow.Conf = conf
|
|
|
|
|
|
|
|
|
|
// Function列表
|
|
|
|
|
flow.Funcs = make(map[string]kis.Function)
|
|
|
|
|
flow.funcParams = make(map[string]config.FParam)
|
|
|
|
|
|
2024-01-03 17:22:35 +08:00
|
|
|
|
// 数据data
|
|
|
|
|
flow.data = make(common.KisDataMap)
|
|
|
|
|
|
2024-01-26 17:27:29 +08:00
|
|
|
|
// 初始化本地缓存
|
|
|
|
|
flow.cache = cache.New(cache.NoExpiration, common.DeFaultFlowCacheCleanUp*time.Minute)
|
|
|
|
|
|
|
|
|
|
// 初始化临时数据
|
|
|
|
|
flow.metaData = make(map[string]interface{})
|
|
|
|
|
|
2023-12-31 18:04:28 +08:00
|
|
|
|
return flow
|
|
|
|
|
}
|
2024-01-01 17:49:27 +08:00
|
|
|
|
|
2024-02-04 16:27:28 +08:00
|
|
|
|
// Fork 得到Flow的一个副本(深拷贝)
|
|
|
|
|
func (flow *KisFlow) Fork(ctx context.Context) kis.Flow {
|
|
|
|
|
|
2024-03-01 16:29:07 +08:00
|
|
|
|
cfg := flow.Conf
|
2024-02-04 16:27:28 +08:00
|
|
|
|
|
|
|
|
|
// 通过之前的配置生成一个新的Flow
|
2024-03-01 16:29:07 +08:00
|
|
|
|
newFlow := NewKisFlow(cfg)
|
2024-02-04 16:27:28 +08:00
|
|
|
|
|
|
|
|
|
for _, fp := range flow.Conf.Flows {
|
|
|
|
|
if _, ok := flow.funcParams[flow.Funcs[fp.FuncName].GetId()]; !ok {
|
2024-03-01 16:29:07 +08:00
|
|
|
|
// 当前function没有配置Params
|
2024-03-29 18:07:57 +08:00
|
|
|
|
_ = newFlow.AppendNewFunction(flow.Funcs[fp.FuncName].GetConfig(), nil)
|
2024-02-04 16:27:28 +08:00
|
|
|
|
} else {
|
2024-03-01 16:29:07 +08:00
|
|
|
|
// 当前function有配置Params
|
2024-03-29 18:07:57 +08:00
|
|
|
|
_ = newFlow.AppendNewFunction(flow.Funcs[fp.FuncName].GetConfig(), fp.Params)
|
2024-02-04 16:27:28 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-04-07 22:39:21 +08:00
|
|
|
|
log.Logger().DebugX(ctx, "=====>Flow Fork, ", "oldFlow.funcParams", flow.funcParams)
|
|
|
|
|
log.Logger().DebugX(ctx, "=====>Flow Fork, ", "newFlow.funcParams", newFlow.GetFuncParamsAllFuncs())
|
2024-02-04 16:27:28 +08:00
|
|
|
|
|
|
|
|
|
return newFlow
|
|
|
|
|
}
|
|
|
|
|
|
2024-03-29 18:07:57 +08:00
|
|
|
|
// Link 将Function链接到Flow中, 同时会将Function的配置参数添加到Flow的配置中
|
2024-01-01 17:49:27 +08:00
|
|
|
|
// fConf: 当前Function策略
|
|
|
|
|
// fParams: 当前Flow携带的Function动态参数
|
|
|
|
|
func (flow *KisFlow) Link(fConf *config.KisFuncConfig, fParams config.FParam) error {
|
2024-03-29 18:07:57 +08:00
|
|
|
|
|
|
|
|
|
// Flow 添加Function
|
|
|
|
|
_ = flow.AppendNewFunction(fConf, fParams)
|
|
|
|
|
|
|
|
|
|
// FlowConfig 添加Function
|
|
|
|
|
flowFuncParam := config.KisFlowFunctionParam{
|
|
|
|
|
FuncName: fConf.FName,
|
|
|
|
|
Params: fParams,
|
|
|
|
|
}
|
|
|
|
|
flow.Conf.AppendFunctionConfig(flowFuncParam)
|
|
|
|
|
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// AppendNewFunction 将一个新的Function追加到到Flow中
|
|
|
|
|
func (flow *KisFlow) AppendNewFunction(fConf *config.KisFuncConfig, fParams config.FParam) error {
|
2024-01-09 17:30:58 +08:00
|
|
|
|
// 创建Function实例
|
2024-01-01 17:49:27 +08:00
|
|
|
|
f := function.NewKisFunction(flow, fConf)
|
|
|
|
|
|
2024-01-09 17:30:58 +08:00
|
|
|
|
if fConf.Option.CName != "" {
|
|
|
|
|
// 当前Function有Connector关联,需要初始化Connector实例
|
|
|
|
|
|
|
|
|
|
// 获取Connector配置
|
|
|
|
|
connConfig, err := fConf.GetConnConfig()
|
|
|
|
|
if err != nil {
|
|
|
|
|
panic(err)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 创建Connector对象
|
|
|
|
|
connector := conn.NewKisConnector(connConfig)
|
|
|
|
|
|
|
|
|
|
// 初始化Connector, 执行Connector Init 方法
|
|
|
|
|
if err = connector.Init(); err != nil {
|
|
|
|
|
panic(err)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 关联Function实例和Connector实例关系
|
|
|
|
|
_ = f.AddConnector(connector)
|
|
|
|
|
}
|
|
|
|
|
|
2024-01-01 17:49:27 +08:00
|
|
|
|
// Flow 添加 Function
|
|
|
|
|
if err := flow.appendFunc(f, fParams); err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// appendFunc 将Function添加到Flow中, 链表操作
|
|
|
|
|
func (flow *KisFlow) appendFunc(function kis.Function, fParam config.FParam) error {
|
|
|
|
|
|
|
|
|
|
if function == nil {
|
|
|
|
|
return errors.New("AppendFunc append nil to List")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
flow.flock.Lock()
|
|
|
|
|
defer flow.flock.Unlock()
|
|
|
|
|
|
|
|
|
|
if flow.FlowHead == nil {
|
|
|
|
|
// 首次添加节点
|
|
|
|
|
flow.FlowHead = function
|
|
|
|
|
flow.FlowTail = function
|
|
|
|
|
|
|
|
|
|
function.SetN(nil)
|
|
|
|
|
function.SetP(nil)
|
|
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
// 将function插入到链表的尾部
|
|
|
|
|
function.SetP(flow.FlowTail)
|
|
|
|
|
function.SetN(nil)
|
|
|
|
|
|
|
|
|
|
flow.FlowTail.SetN(function)
|
|
|
|
|
flow.FlowTail = function
|
|
|
|
|
}
|
|
|
|
|
|
2024-03-01 16:29:07 +08:00
|
|
|
|
// 将Function Name 详细Hash对应关系添加到flow对象中
|
2024-01-12 17:27:43 +08:00
|
|
|
|
flow.Funcs[function.GetConfig().FName] = function
|
2024-01-01 17:49:27 +08:00
|
|
|
|
|
2024-03-01 16:29:07 +08:00
|
|
|
|
// 先添加function 默认携带的Params参数
|
2024-01-01 17:49:27 +08:00
|
|
|
|
params := make(config.FParam)
|
|
|
|
|
for key, value := range function.GetConfig().Option.Params {
|
|
|
|
|
params[key] = value
|
|
|
|
|
}
|
|
|
|
|
|
2024-03-01 16:29:07 +08:00
|
|
|
|
// 再添加flow携带的function定义参数(重复即覆盖)
|
2024-01-01 17:49:27 +08:00
|
|
|
|
for key, value := range fParam {
|
|
|
|
|
params[key] = value
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 将得到的FParams存留在flow结构体中,用来function业务直接通过Hash获取
|
|
|
|
|
// key 为当前Function的KisId,不用Fid的原因是为了防止一个Flow添加两个相同策略Id的Function
|
2024-01-03 10:16:54 +08:00
|
|
|
|
flow.funcParams[function.GetId()] = params
|
2024-01-01 17:49:27 +08:00
|
|
|
|
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Run 启动KisFlow的流式计算, 从起始Function开始执行流
|
|
|
|
|
func (flow *KisFlow) Run(ctx context.Context) error {
|
|
|
|
|
|
|
|
|
|
var fn kis.Function
|
|
|
|
|
|
|
|
|
|
fn = flow.FlowHead
|
2024-01-23 16:21:02 +08:00
|
|
|
|
flow.abort = false
|
2024-01-01 17:49:27 +08:00
|
|
|
|
|
|
|
|
|
if flow.Conf.Status == int(common.FlowDisable) {
|
2024-03-01 16:29:07 +08:00
|
|
|
|
// flow被配置关闭
|
2024-01-01 17:49:27 +08:00
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
2024-03-18 09:29:05 +08:00
|
|
|
|
// Metrics
|
|
|
|
|
var funcStart time.Time
|
|
|
|
|
var flowStart time.Time
|
|
|
|
|
|
2024-01-03 17:22:35 +08:00
|
|
|
|
// 因为此时还没有执行任何Function, 所以PrevFunctionId为FirstVirtual 因为没有上一层Function
|
|
|
|
|
flow.PrevFunctionId = common.FunctionIdFirstVirtual
|
|
|
|
|
|
|
|
|
|
// 提交数据流原始数据
|
|
|
|
|
if err := flow.commitSrcData(ctx); err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
|
2024-03-18 09:29:05 +08:00
|
|
|
|
// Metrics
|
|
|
|
|
if config.GlobalConfig.EnableProm == true {
|
|
|
|
|
// 统计Flow的调度次数
|
|
|
|
|
metrics.Metrics.FlowScheduleCntsToTal.WithLabelValues(flow.Name).Inc()
|
|
|
|
|
// 统计Flow的执行消耗时长
|
|
|
|
|
flowStart = time.Now()
|
|
|
|
|
}
|
|
|
|
|
|
2024-03-01 16:29:07 +08:00
|
|
|
|
// 流式链式调用
|
2024-01-23 16:21:02 +08:00
|
|
|
|
for fn != nil && flow.abort == false {
|
2024-01-03 17:22:35 +08:00
|
|
|
|
|
|
|
|
|
// flow记录当前执行到的Function 标记
|
|
|
|
|
fid := fn.GetId()
|
|
|
|
|
flow.ThisFunction = fn
|
|
|
|
|
flow.ThisFunctionId = fid
|
|
|
|
|
|
2024-03-18 09:29:05 +08:00
|
|
|
|
fName := fn.GetConfig().FName
|
|
|
|
|
fMode := fn.GetConfig().FMode
|
|
|
|
|
|
|
|
|
|
if config.GlobalConfig.EnableProm == true {
|
|
|
|
|
// 统计Function调度次数
|
|
|
|
|
metrics.Metrics.FuncScheduleCntsTotal.WithLabelValues(fName, fMode).Inc()
|
|
|
|
|
|
|
|
|
|
// 统计Function 耗时 记录开始时间
|
|
|
|
|
funcStart = time.Now()
|
|
|
|
|
}
|
|
|
|
|
|
2024-01-03 17:22:35 +08:00
|
|
|
|
// 得到当前Function要处理与的源数据
|
|
|
|
|
if inputData, err := flow.getCurData(); err != nil {
|
2024-04-07 22:39:21 +08:00
|
|
|
|
log.Logger().ErrorX(ctx, "flow.Run(): getCurData", "err", err.Error())
|
2024-01-03 17:22:35 +08:00
|
|
|
|
return err
|
|
|
|
|
} else {
|
|
|
|
|
flow.inPut = inputData
|
|
|
|
|
}
|
|
|
|
|
|
2024-01-01 17:49:27 +08:00
|
|
|
|
if err := fn.Call(ctx, flow); err != nil {
|
2024-03-01 16:29:07 +08:00
|
|
|
|
// Error
|
2024-01-01 17:49:27 +08:00
|
|
|
|
return err
|
|
|
|
|
} else {
|
2024-03-01 16:29:07 +08:00
|
|
|
|
// Success
|
2024-01-23 16:21:02 +08:00
|
|
|
|
fn, err = flow.dealAction(ctx, fn)
|
|
|
|
|
if err != nil {
|
2024-01-03 17:22:35 +08:00
|
|
|
|
return err
|
|
|
|
|
}
|
2024-03-18 09:29:05 +08:00
|
|
|
|
|
|
|
|
|
// 统计Function 耗时
|
|
|
|
|
if config.GlobalConfig.EnableProm == true {
|
|
|
|
|
// Function消耗时间
|
|
|
|
|
duration := time.Since(funcStart)
|
|
|
|
|
|
|
|
|
|
// 统计当前Function统计指标,做时间统计
|
|
|
|
|
metrics.Metrics.FunctionDuration.With(
|
|
|
|
|
prometheus.Labels{
|
|
|
|
|
common.LABEL_FUNCTION_NAME: fName,
|
|
|
|
|
common.LABEL_FUNCTION_MODE: fMode}).Observe(duration.Seconds() * 1000)
|
|
|
|
|
}
|
|
|
|
|
|
2024-01-01 17:49:27 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-03-18 09:29:05 +08:00
|
|
|
|
// Metrics
|
|
|
|
|
if config.GlobalConfig.EnableProm == true {
|
|
|
|
|
// 统计Flow执行耗时
|
|
|
|
|
duration := time.Since(flowStart)
|
|
|
|
|
metrics.Metrics.FlowDuration.WithLabelValues(flow.Name).Observe(duration.Seconds() * 1000)
|
|
|
|
|
}
|
|
|
|
|
|
2024-01-01 17:49:27 +08:00
|
|
|
|
return nil
|
|
|
|
|
}
|
2024-01-04 16:36:36 +08:00
|
|
|
|
|
2024-01-23 16:21:02 +08:00
|
|
|
|
// Next 当前Flow执行到的Function进入下一层Function所携带的Action动作
|
|
|
|
|
func (flow *KisFlow) Next(acts ...kis.ActionFunc) error {
|
|
|
|
|
|
|
|
|
|
// 加载Function FaaS 传递的 Action动作
|
|
|
|
|
flow.action = kis.LoadActions(acts)
|
|
|
|
|
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
2024-01-04 16:36:36 +08:00
|
|
|
|
func (flow *KisFlow) GetName() string {
|
|
|
|
|
return flow.Name
|
|
|
|
|
}
|
|
|
|
|
|
2024-04-15 10:44:57 +08:00
|
|
|
|
func (flow *KisFlow) GetId() string {
|
|
|
|
|
return flow.Id
|
|
|
|
|
}
|
|
|
|
|
|
2024-01-04 16:36:36 +08:00
|
|
|
|
func (flow *KisFlow) GetThisFunction() kis.Function {
|
|
|
|
|
return flow.ThisFunction
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (flow *KisFlow) GetThisFuncConf() *config.KisFuncConfig {
|
|
|
|
|
return flow.ThisFunction.GetConfig()
|
|
|
|
|
}
|
2024-01-09 17:30:58 +08:00
|
|
|
|
|
|
|
|
|
// GetConnector 得到当前正在执行的Function的Connector
|
|
|
|
|
func (flow *KisFlow) GetConnector() (kis.Connector, error) {
|
2024-03-01 16:29:07 +08:00
|
|
|
|
if connector := flow.ThisFunction.GetConnector(); connector != nil {
|
|
|
|
|
return connector, nil
|
2024-01-09 17:30:58 +08:00
|
|
|
|
} else {
|
|
|
|
|
return nil, errors.New("GetConnector(): Connector is nil")
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// GetConnConf 得到当前正在执行的Function的Connector的配置
|
|
|
|
|
func (flow *KisFlow) GetConnConf() (*config.KisConnConfig, error) {
|
2024-03-01 16:29:07 +08:00
|
|
|
|
if connector := flow.ThisFunction.GetConnector(); connector != nil {
|
|
|
|
|
return connector.GetConfig(), nil
|
2024-01-09 17:30:58 +08:00
|
|
|
|
} else {
|
|
|
|
|
return nil, errors.New("GetConnConf(): Connector is nil")
|
|
|
|
|
}
|
|
|
|
|
}
|
2024-01-12 17:27:43 +08:00
|
|
|
|
|
|
|
|
|
func (flow *KisFlow) GetConfig() *config.KisFlowConfig {
|
|
|
|
|
return flow.Conf
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// GetFuncConfigByName 得到当前Flow的配置
|
|
|
|
|
func (flow *KisFlow) GetFuncConfigByName(funcName string) *config.KisFuncConfig {
|
|
|
|
|
if f, ok := flow.Funcs[funcName]; ok {
|
|
|
|
|
return f.GetConfig()
|
|
|
|
|
} else {
|
2024-04-07 22:39:21 +08:00
|
|
|
|
log.Logger().Error("GetFuncConfigByName(): Function not found", "FunctionName", funcName)
|
2024-01-12 17:27:43 +08:00
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
}
|