From eaf20c4e3accb7c91cfb278060a170c487a25246 Mon Sep 17 00:00:00 2001 From: boyce <6549168@qq.com> Date: Mon, 17 Nov 2025 15:01:51 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E8=93=9D=E5=9B=BE=E7=83=AD?= =?UTF-8?q?=E6=9B=B4=E6=96=B0=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- event/eventtype.go | 6 +- util/blueprint/blueprint.go | 149 ++++++++++++++++++++++++++---------- util/blueprint/graph.go | 18 ++++- util/blueprint/graphpool.go | 9 +++ 4 files changed, 136 insertions(+), 46 deletions(-) diff --git a/event/eventtype.go b/event/eventtype.go index 7203711..4ca0137 100644 --- a/event/eventtype.go +++ b/event/eventtype.go @@ -10,7 +10,7 @@ const ( Sys_Event_Tcp EventType = -3 Sys_Event_Http_Event EventType = -4 Sys_Event_WebSocket EventType = -5 - Sys_Event_Kcp EventType = -6 + Sys_Event_Kcp EventType = -6 Sys_Event_Node_Conn_Event EventType = -7 Sys_Event_Nats_Conn_Event EventType = -8 Sys_Event_DiscoverService EventType = -9 @@ -18,6 +18,6 @@ const ( Sys_Event_EtcdDiscovery EventType = -11 Sys_Event_Gin_Event EventType = -12 Sys_Event_FrameTick EventType = -13 - - Sys_Event_User_Define EventType = 1 + Sys_Event_ReloadBlueprint EventType = -14 + Sys_Event_User_Define EventType = 1 ) diff --git a/util/blueprint/blueprint.go b/util/blueprint/blueprint.go index d9aa14a..38d1633 100644 --- a/util/blueprint/blueprint.go +++ b/util/blueprint/blueprint.go @@ -3,84 +3,153 @@ package blueprint import ( "fmt" "sync/atomic" + "github.com/duanhf2012/origin/v2/log" ) type Blueprint struct { execNodes []IExecNode // 注册的定义执行结点 - - execPool ExecPool - graphPool GraphPool + execNodeList []func() IExecNode + execPool *ExecPool + graphPool *GraphPool blueprintModule IBlueprintModule mapGraph map[int64]IGraph seedID int64 cancelTimer func(*uint64) bool + + execDefFilePath string // 执行结点定义文件路径 + graphFilePath string // 蓝图文件路径 } -func (bm *Blueprint) RegExecNode(execNode IExecNode) { - bm.execNodes = append(bm.execNodes, execNode) +func (bm *Blueprint) RegisterExecNode(execNodeFunc func() IExecNode) { + bm.execNodeList = append(bm.execNodeList, execNodeFunc) } -func (bm *Blueprint) regSysNode() { - bm.RegExecNode(&AddInt{}) - bm.RegExecNode(&SubInt{}) - bm.RegExecNode(&MulInt{}) - bm.RegExecNode(&DivInt{}) - bm.RegExecNode(&ModInt{}) - bm.RegExecNode(&RandNumber{}) +type IExecNodeType[T any] interface { + *T + IExecNode +} - bm.RegExecNode(&Entrance_ArrayParam{}) - bm.RegExecNode(&Entrance_IntParam{}) - bm.RegExecNode(&Entrance_Timer{}) - bm.RegExecNode(&DebugOutput{}) - bm.RegExecNode(&Sequence{}) - bm.RegExecNode(&Foreach{}) - bm.RegExecNode(&ForeachIntArray{}) +// 生成一个泛型函数,返回func() IExecNode类型 +func NewExecNode[T any, P IExecNodeType[T]]() func() IExecNode { + return func() IExecNode { + var t T + return P(&t) + } +} - bm.RegExecNode(&GetArrayInt{}) - bm.RegExecNode(&GetArrayString{}) - bm.RegExecNode(&GetArrayLen{}) - bm.RegExecNode(&CreateIntArray{}) - bm.RegExecNode(&CreateStringArray{}) - bm.RegExecNode(&AppendIntegerToArray{}) - bm.RegExecNode(&AppendStringToArray{}) +func (bm *Blueprint) regSysNodes() { + bm.RegisterExecNode(NewExecNode[AddInt]()) + bm.RegisterExecNode(NewExecNode[SubInt]()) + bm.RegisterExecNode(NewExecNode[MulInt]()) + bm.RegisterExecNode(NewExecNode[DivInt]()) + bm.RegisterExecNode(NewExecNode[ModInt]()) + bm.RegisterExecNode(NewExecNode[RandNumber]()) + + bm.RegisterExecNode(NewExecNode[Entrance_ArrayParam]()) + bm.RegisterExecNode(NewExecNode[Entrance_IntParam]()) + bm.RegisterExecNode(NewExecNode[Entrance_Timer]()) + bm.RegisterExecNode(NewExecNode[DebugOutput]()) + bm.RegisterExecNode(NewExecNode[Sequence]()) + bm.RegisterExecNode(NewExecNode[Foreach]()) + bm.RegisterExecNode(NewExecNode[ForeachIntArray]()) + + bm.RegisterExecNode(NewExecNode[GetArrayInt]()) + bm.RegisterExecNode(NewExecNode[GetArrayString]()) + bm.RegisterExecNode(NewExecNode[GetArrayLen]()) + bm.RegisterExecNode(NewExecNode[CreateIntArray]()) + bm.RegisterExecNode(NewExecNode[CreateStringArray]()) + bm.RegisterExecNode(NewExecNode[AppendIntegerToArray]()) + bm.RegisterExecNode(NewExecNode[AppendStringToArray]()) + bm.RegisterExecNode(NewExecNode[BoolIf]()) + bm.RegisterExecNode(NewExecNode[GreaterThanInteger]()) + bm.RegisterExecNode(NewExecNode[LessThanInteger]()) + bm.RegisterExecNode(NewExecNode[EqualInteger]()) + bm.RegisterExecNode(NewExecNode[RangeCompare]()) + bm.RegisterExecNode(NewExecNode[EqualSwitch]()) + bm.RegisterExecNode(NewExecNode[Probability]()) + bm.RegisterExecNode(NewExecNode[CreateTimer]()) +} + + +func (bm *Blueprint) StartHotReload() (func(),error) { + var execPool ExecPool + var graphPool GraphPool + + // 加载配置结点生成名字对应的innerExecNode + err := execPool.Load(bm.execDefFilePath) + if err != nil { + return nil, err + } + + // 将注册的实际执行结点与innerExecNode进行关联 + for _, newExec := range bm.execNodeList { + e := newExec() + if !execPool.Register(e) { + return nil,fmt.Errorf("register exec failed,exec:%s", e.GetName()) + } + } + + // 加载所有的vgf蓝图文件 + err = graphPool.Load(&execPool, bm.graphFilePath, bm.blueprintModule) + if err != nil { + return nil, err + } + + // 返回配置加载后的刷新内存处理 + return func() { + // 替换旧的执行池和图池 + bm.execPool = &execPool + bm.graphPool = &graphPool + + for _, gh := range bm.mapGraph { + gFileName := gh.GetGraphFileName() + bGraph := bm.graphPool.GetBaseGraph(gFileName) + if bGraph == nil { + log.Warn("GetBaseGraph fail", log.String("graph file name", gFileName)) + bGraph = &baseGraph{entrance: map[int64]*execNode{}} + } + + gh.HotReload(bGraph) + } + }, nil - bm.RegExecNode(&BoolIf{}) - bm.RegExecNode(&GreaterThanInteger{}) - bm.RegExecNode(&LessThanInteger{}) - bm.RegExecNode(&EqualInteger{}) - bm.RegExecNode(&RangeCompare{}) - bm.RegExecNode(&EqualSwitch{}) - bm.RegExecNode(&Probability{}) - bm.RegExecNode(&CreateTimer{}) } func (bm *Blueprint) Init(execDefFilePath string, graphFilePath string, blueprintModule IBlueprintModule, cancelTimer func(*uint64) bool) error { + var execPool ExecPool + var graphPool GraphPool + // 加载配置结点生成名字对应的innerExecNode - err := bm.execPool.Load(execDefFilePath) + err := execPool.Load(execDefFilePath) if err != nil { return err } // 注册系统执行结点 - bm.regSysNode() + bm.regSysNodes() // 将注册的实际执行结点与innerExecNode进行关联 - for _, e := range bm.execNodes { - if !bm.execPool.Register(e) { + for _, newExec := range bm.execNodeList { + e := newExec() + if !execPool.Register(e) { return fmt.Errorf("register exec failed,exec:%s", e.GetName()) } } // 加载所有的vgf蓝图文件 - err = bm.graphPool.Load(&bm.execPool, graphFilePath, blueprintModule) + err = graphPool.Load(&execPool, graphFilePath, blueprintModule) if err != nil { return err } - + + bm.execPool = &execPool + bm.graphPool = &graphPool bm.cancelTimer = cancelTimer bm.blueprintModule = blueprintModule bm.mapGraph = make(map[int64]IGraph, 128) + bm.execDefFilePath = execDefFilePath + bm.graphFilePath = graphFilePath return nil } diff --git a/util/blueprint/graph.go b/util/blueprint/graph.go index 802b316..6526043 100644 --- a/util/blueprint/graph.go +++ b/util/blueprint/graph.go @@ -4,16 +4,20 @@ import ( "fmt" "time" + "github.com/duanhf2012/origin/v2/log" "github.com/duanhf2012/origin/v2/service" "github.com/goccy/go-json" - "github.com/duanhf2012/origin/v2/log" ) const ReturnVarial = "g_Return" + var IsDebug = false + type IGraph interface { Do(entranceID int64, args ...any) (Port_Array, error) Release() + GetGraphFileName() string + HotReload(newBaseGraph *baseGraph) } type IBlueprintModule interface { @@ -30,7 +34,7 @@ type baseGraph struct { type Graph struct { graphFileName string - graphID int64 + graphID int64 *baseGraph graphContext IBlueprintModule @@ -140,7 +144,7 @@ func (gc *graphConfig) GetNodeByID(nodeID string) *nodeConfig { func (gr *Graph) Do(entranceID int64, args ...any) (Port_Array, error) { if IsDebug { - log.Debug("Graph Do", log.String("graphName",gr.graphFileName),log.Int64("graphID", gr.graphID), log.Int64("entranceID", entranceID)) + log.Debug("Graph Do", log.String("graphName", gr.graphFileName), log.Int64("graphID", gr.graphID), log.Int64("entranceID", entranceID)) } entranceNode := gr.entrance[entranceID] @@ -204,3 +208,11 @@ func (gr *Graph) Release() { // 清理掉所有数据 *gr = Graph{} } + +func (gr *Graph) HotReload(newBaseGraph *baseGraph) { + gr.baseGraph = newBaseGraph +} + +func (gr *Graph) GetGraphFileName() string{ + return gr.graphFileName +} diff --git a/util/blueprint/graphpool.go b/util/blueprint/graphpool.go index 72a40d2..8012833 100644 --- a/util/blueprint/graphpool.go +++ b/util/blueprint/graphpool.go @@ -52,6 +52,15 @@ func (gp *GraphPool) Load(execPool *ExecPool, graphFilePath string, blueprintMod }) } +func (gp *GraphPool) GetBaseGraph(graphName string) *baseGraph { + gr, ok := gp.mapGraphs[graphName] + if !ok { + return nil + } + + return gr +} + func (gp *GraphPool) Create(graphName string, graphID int64) IGraph { gr, ok := gp.mapGraphs[graphName] if !ok {