github.com/15mga/kiwi@v0.0.2-0.20240324021231-b95d5c3ac751/graph/graph.go (about) 1 package graph 2 3 import ( 4 "github.com/15mga/kiwi" 5 "github.com/15mga/kiwi/util" 6 ) 7 8 type IGraph interface { 9 Name() string 10 Data() util.M 11 SetData(m util.M) 12 Plugin() IPlugin 13 SetPlugin(plugin IPlugin) 14 Start() *util.Err 15 AddNode(name string) (INode, *util.Err) 16 GetNode(name string) (INode, *util.Err) 17 GetNodeByPath(names ...string) (INode, *util.Err) 18 FindNode(name string) (INode, bool) 19 FindNodes(name string, nodes *[]INode) 20 IterNode(fn func(INode)) 21 AnyNode(fn func(INode) bool) bool 22 Link(outNode, outPoint, inNode, inPoint string) (ILink, *util.Err) 23 IterLink(fn func(ILink)) 24 AnyLink(fn func(ILink) bool) bool 25 AddSubGraph(name string) (ISubGraph, *util.Err) 26 GetSubGraph(graph string) (ISubGraph, *util.Err) 27 IterSubGraph(fn func(ISubGraph)) 28 AnySubGraph(fn func(ISubGraph) bool) bool 29 } 30 31 type ( 32 option struct { 33 plugin IPlugin 34 } 35 Option func(*option) 36 ) 37 38 func Plugin(plugin IPlugin) Option { 39 return func(o *option) { 40 o.plugin = plugin 41 } 42 } 43 44 func NewGraph(name string, opts ...Option) IGraph { 45 opt := &option{} 46 for _, o := range opts { 47 o(opt) 48 } 49 g := &graph{ 50 option: opt, 51 name: name, 52 data: util.M{}, 53 nameToNode: make(map[string]INode), 54 nameToGraph: make(map[string]ISubGraph), 55 nameToLink: make(map[string]ILink), 56 } 57 return g 58 } 59 60 type graph struct { 61 option *option 62 name string 63 data util.M 64 nameToNode map[string]INode 65 nameToGraph map[string]ISubGraph 66 nameToLink map[string]ILink 67 } 68 69 func (g *graph) Name() string { 70 return g.name 71 } 72 73 func (g *graph) Data() util.M { 74 return g.data 75 } 76 77 func (g *graph) SetData(data util.M) { 78 g.data = data 79 } 80 81 func (g *graph) Plugin() IPlugin { 82 return g.option.plugin 83 } 84 85 func (g *graph) SetPlugin(plugin IPlugin) { 86 g.option.plugin = plugin 87 } 88 89 func (g *graph) Start() *util.Err { 90 for _, nd := range g.nameToNode { 91 err := nd.Start() 92 if err != nil { 93 return err 94 } 95 } 96 for _, lnk := range g.nameToLink { 97 err := lnk.Start() 98 if err != nil { 99 return err 100 } 101 } 102 if g.option.plugin != nil { 103 g.option.plugin.OnStart(g) 104 } 105 return nil 106 } 107 108 func (g *graph) AddNode(name string) (INode, *util.Err) { 109 _, ok := g.nameToNode[name] 110 if ok { 111 return nil, util.NewErr(util.EcExist, util.M{ 112 "node name": name, 113 "graph": g.Name(), 114 }) 115 } 116 nd := NewNode(g, name) 117 g.nameToNode[name] = nd 118 if g.option.plugin != nil { 119 g.option.plugin.OnAddNode(g, nd) 120 } 121 return nd, nil 122 } 123 124 func (g *graph) GetNode(name string) (INode, *util.Err) { 125 n, ok := g.nameToNode[name] 126 if ok { 127 return n, nil 128 } 129 return nil, util.NewErr(util.EcNotExist, util.M{ 130 "node name": name, 131 "graph": g.Name(), 132 }) 133 } 134 135 func (g *graph) GetNodeByPath(names ...string) (INode, *util.Err) { 136 switch len(names) { 137 case 0: 138 return nil, util.NewErr(util.EcLengthErr, nil) 139 case 1: 140 return g.GetNode(names[0]) 141 default: 142 sgn := names[0] 143 sg, ok := g.nameToGraph[sgn] 144 if !ok { 145 return nil, util.NewErr(util.EcNotExist, util.M{ 146 "subgraph name": sgn, 147 "graph": g.Name(), 148 }) 149 } 150 return sg.GetNodeByPath(names[1:]...) 151 } 152 } 153 154 func (g *graph) FindNode(name string) (INode, bool) { 155 for nm, nd := range g.nameToNode { 156 if nm == name { 157 return nd, true 158 } 159 } 160 return nil, false 161 } 162 163 func (g *graph) FindNodes(name string, nodes *[]INode) { 164 for nm, nd := range g.nameToNode { 165 if nm == name { 166 *nodes = append(*nodes, nd) 167 } 168 } 169 for _, sg := range g.nameToGraph { 170 sg.FindNodes(name, nodes) 171 } 172 } 173 174 func (g *graph) IterNode(fn func(INode)) { 175 for _, nd := range g.nameToNode { 176 fn(nd) 177 } 178 } 179 180 func (g *graph) AnyNode(fn func(INode) bool) bool { 181 for _, nd := range g.nameToNode { 182 if fn(nd) { 183 return true 184 } 185 } 186 return false 187 } 188 189 func (g *graph) Link(outNode, outPoint, inNode, inPoint string) (ILink, *util.Err) { 190 name := LinkName(outNode, outPoint, inNode, inPoint) 191 _, ok := g.nameToLink[name] 192 if ok { 193 return nil, util.NewErr(util.EcExist, util.M{ 194 "name": name, 195 "graph": g.Name(), 196 }) 197 } 198 199 on, err := g.GetNode(outNode) 200 if err != nil { 201 err.AddParam("graph", g.Name()) 202 return nil, err 203 } 204 op, err := on.GetOut(outPoint) 205 if err != nil { 206 err.AddParam("graph", g.Name()) 207 return nil, err 208 } 209 210 in, err := g.GetNode(inNode) 211 if err != nil { 212 err.AddParam("graph", g.Name()) 213 return nil, err 214 } 215 ip, err := in.GetIn(inPoint) 216 if err != nil { 217 err.AddParam("graph", g.Name()) 218 return nil, err 219 } 220 221 if ip.Type() != op.Type() { 222 return nil, util.NewErr(util.EcParamsErr, util.M{ 223 "name": name, 224 "graph": g.Name(), 225 "in node type": ip.Type(), 226 "out node type": op.Type(), 227 }) 228 } 229 230 lnk := newLink(g, name, op, ip) 231 op.AddLink(lnk) 232 ip.AddLink(lnk) 233 g.nameToLink[name] = lnk 234 if g.option.plugin != nil { 235 g.option.plugin.OnAddLink(g, lnk) 236 } 237 return lnk, nil 238 } 239 240 func (g *graph) IterLink(fn func(ILink)) { 241 for _, lnk := range g.nameToLink { 242 fn(lnk) 243 } 244 } 245 246 func (g *graph) AnyLink(fn func(ILink) bool) bool { 247 for _, lnk := range g.nameToLink { 248 if fn(lnk) { 249 return true 250 } 251 } 252 return false 253 } 254 255 func (g *graph) AddSubGraph(name string) (ISubGraph, *util.Err) { 256 _, ok := g.nameToNode[name] 257 if ok { 258 return nil, util.NewErr(util.EcExist, util.M{ 259 "name": name, 260 "graph": g.Name(), 261 }) 262 } 263 sg := newSubGraph(g, name) 264 g.nameToGraph[name] = sg 265 g.nameToNode[name] = sg 266 if g.option.plugin != nil { 267 g.option.plugin.OnAddNode(g, sg) 268 g.option.plugin.OnAddSubGraph(g, sg) 269 } 270 return sg, nil 271 } 272 273 func (g *graph) GetSubGraph(name string) (ISubGraph, *util.Err) { 274 sg, ok := g.nameToGraph[name] 275 if !ok { 276 return nil, util.NewErr(util.EcNotExist, util.M{ 277 "name": name, 278 "graph": g.Name(), 279 }) 280 } 281 return sg, nil 282 } 283 284 func (g *graph) IterSubGraph(fn func(ISubGraph)) { 285 for _, sg := range g.nameToGraph { 286 fn(sg) 287 } 288 } 289 290 func (g *graph) AnySubGraph(fn func(ISubGraph) bool) bool { 291 for _, sg := range g.nameToGraph { 292 if fn(sg) { 293 return true 294 } 295 } 296 return false 297 } 298 299 func NewGraphWithConf(conf Conf, opts ...Option) IGraph { 300 g := NewGraph(conf.Name, opts...) 301 for _, nc := range conf.Nodes { 302 _, err := AddNodeWithConf(g, nc) 303 if err != nil { 304 kiwi.Error(err) 305 } 306 } 307 for _, gc := range conf.SubGraphs { 308 _, err := AddSubGraphWithConf(g, gc) 309 if err != nil { 310 kiwi.Error(err) 311 } 312 } 313 for _, lc := range conf.Links { 314 _, err := LinkWithConf(g, lc) 315 if err != nil { 316 kiwi.Error(err) 317 } 318 } 319 return g 320 } 321 322 func AddNodeWithConf(g IGraph, conf NodeConf) (INode, *util.Err) { 323 n, err := g.AddNode(conf.Name) 324 if err != nil { 325 return nil, err 326 } 327 n.SetComment(conf.Comment) 328 if conf.M != nil { 329 n.SetData(conf.M) 330 } else { 331 n.SetData(util.M{}) 332 } 333 334 for _, ip := range conf.Ins { 335 err := n.AddIn(ip.Type, ip.Name) 336 if err != nil { 337 kiwi.Error(err) 338 } 339 } 340 for _, op := range conf.Outs { 341 err := n.AddOut(op.Type, op.Name) 342 if err != nil { 343 kiwi.Error(err) 344 } 345 } 346 347 for pnt, name := range conf.PointToProcessor { 348 pcr, ok := _MsgProcessors[name] 349 if !ok { 350 kiwi.Error2(util.EcNotExist, util.M{ 351 "name": name, 352 }) 353 continue 354 } 355 n.BindFn(pnt, pcr) 356 } 357 return n, nil 358 } 359 360 func AddSubGraphWithConf(g IGraph, conf SubConf) (ISubGraph, *util.Err) { 361 sg, err := g.AddSubGraph(conf.Name) 362 if err != nil { 363 err.AddParam("graph", g.Name()) 364 return nil, err 365 } 366 367 for _, nc := range conf.Nodes { 368 _, err = AddNodeWithConf(sg, nc) 369 if err != nil { 370 err.AddParam("graph", g.Name()) 371 kiwi.Error(err) 372 } 373 } 374 375 for _, gc := range conf.SubGraphs { 376 _, err = AddSubGraphWithConf(sg, gc) 377 if err != nil { 378 err.AddParam("graph", g.Name()) 379 kiwi.Error(err) 380 } 381 } 382 _ = sg.SetInNode(conf.In) 383 _ = sg.SetOutNode(conf.Out) 384 385 for _, lc := range conf.Links { 386 _, err = LinkWithConf(sg, lc) 387 if err != nil { 388 err.AddParam("graph", g.Name()) 389 kiwi.Error(err) 390 } 391 } 392 return sg, nil 393 } 394 395 func LinkWithConf(g IGraph, conf LinkConf) (ILink, *util.Err) { 396 return g.Link(conf.OutNode, conf.OutPoint, conf.InNode, conf.InPoint) 397 }