123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556 |
- package service
- import (
- "context"
- "fmt"
- "time"
- "go-common/app/admin/main/aegis/model"
- "go-common/app/admin/main/aegis/model/net"
- "go-common/library/ecode"
- "go-common/library/log"
- )
- //ShowDirection .
- func (s *Service) ShowDirection(c context.Context, id int64) (r *net.ShowDirectionResult, err error) {
- var (
- d *net.Direction
- f *net.Flow
- t *net.Transition
- )
- if d, err = s.gorm.DirectionByID(c, id); err != nil {
- return
- }
- if f, err = s.gorm.FlowByID(c, d.FlowID); err != nil {
- return
- }
- if t, err = s.gorm.TransitionByID(c, d.TransitionID); err != nil {
- return
- }
- r = &net.ShowDirectionResult{
- Direction: d,
- FlowName: f.ChName,
- TransitionName: t.ChName,
- }
- return
- }
- //GetDirectionList .
- func (s *Service) GetDirectionList(c context.Context, pm *net.ListDirectionParam) (result *net.ListDirectionRes, err error) {
- var (
- n *net.Net
- flows map[int64]string
- trans map[int64]string
- unames map[int64]string
- fids = []int64{}
- tids = []int64{}
- uid = []int64{}
- )
- if n, err = s.gorm.NetByID(c, pm.NetID); err != nil {
- return
- }
- if result, err = s.gorm.DirectionList(c, pm); err != nil {
- return
- }
- if len(result.Result) == 0 {
- return
- }
- for _, item := range result.Result {
- fids = append(fids, item.FlowID)
- tids = append(tids, item.TransitionID)
- uid = append(uid, item.UID)
- }
- if flows, err = s.gorm.ColumnMapString(c, net.TableFlow, "ch_name", fids, ""); err != nil {
- return
- }
- if trans, err = s.gorm.ColumnMapString(c, net.TableTransition, "ch_name", tids, ""); err != nil {
- return
- }
- if unames, err = s.http.GetUnames(c, uid); err != nil {
- log.Error("GetDirectionList s.http.GetUnames error(%v)", err)
- err = nil
- }
- for _, item := range result.Result {
- item.NetName = n.ChName
- item.FlowName = flows[item.FlowID]
- item.TransitionName = trans[item.TransitionID]
- item.UserName = unames[item.UID]
- }
- return
- }
- //SwitchDirection .
- func (s *Service) SwitchDirection(c context.Context, id int64, needDisable bool) (err error, msg string) {
- var (
- old *net.Direction
- action string
- canUpdate bool
- )
- if old, err = s.gorm.DirectionByID(c, id); err != nil {
- log.Error("SwitchDirection s.gorm.DirectionByID(%d) error(%v) needDisable(%v)", id, err, needDisable)
- return
- }
- available := old.IsAvailable()
- if available == !needDisable {
- return
- }
- if canUpdate, err = s.beforeUpdate(c, old.NetID); err != nil {
- log.Error("SwitchDirection s.beforeUpdate error(%v)", err)
- return
- }
- if !canUpdate {
- log.Error("SwitchDirection can't update id(%d) needdisable(%v)", id, needDisable)
- return
- }
- if needDisable {
- old.DisableTime = time.Now()
- action = model.LogNetActionDisable
- } else {
- if err = s.checkDirectionBindAvailable(c, old.FlowID, old.TransitionID); err != nil {
- log.Error("SwitchDirection s.checkDirectionBindAvailable(%+v) error(%v) needDisable(%v)", old, err, needDisable)
- return
- }
- if err, msg = s.checkDirConflict(c, old); err != nil {
- log.Error("SwitchDirection s.checkDirConflict(%+v) error(%v) needDisable(%v)", old, err, needDisable)
- return
- }
- old.DisableTime = net.Recovered
- action = model.LogNetActionAvailable
- }
- tx, err := s.gorm.BeginTx(c)
- if err != nil {
- log.Error("SwitchDirection s.gorm.BeginTx error(%v)", err)
- return
- }
- if err = s.gorm.DisableNet(c, tx, old.NetID); err != nil {
- tx.Rollback()
- return
- }
- if err = s.gorm.UpdateFields(c, tx, net.TableDirection, id, map[string]interface{}{"disable_time": old.DisableTime}); err != nil {
- tx.Rollback()
- return
- }
- if err = tx.Commit().Error; err != nil {
- log.Error("SwitchDirection tx.Commit error(%v)", err)
- return
- }
- s.delDirCache(c, old)
- //日志
- oper := &model.NetConfOper{
- OID: old.ID,
- Action: action,
- UID: old.UID,
- NetID: old.NetID,
- FlowID: old.FlowID,
- TranID: old.TransitionID,
- }
- s.sendNetConfLog(c, model.LogTypeDirConf, oper)
- return
- }
- func (s *Service) checkDirectionUnique(c context.Context, netID int64, FlowID int64, transitionID int64, direction int8) (err error, msg string) {
- var exist *net.Direction
- if exist, err = s.gorm.DirectionByUnique(c, netID, FlowID, transitionID, direction); err != nil {
- return
- }
- if exist != nil {
- err = ecode.AegisUniqueAlreadyExist
- msg = fmt.Sprintf(ecode.AegisUniqueAlreadyExist.Message(), "有向线", "")
- }
- return
- }
- func (s *Service) checkDirectionBindAvailable(c context.Context, flowID, transitionID int64) (err error) {
- var (
- f *net.Flow
- t *net.Transition
- )
- if flowID > 0 {
- if f, err = s.gorm.FlowByID(c, flowID); err != nil {
- return
- }
- if !f.IsAvailable() {
- err = ecode.AegisFlowDisabled
- return
- }
- }
- if transitionID > 0 {
- if t, err = s.gorm.TransitionByID(c, transitionID); err != nil {
- return
- }
- if !t.IsAvailable() {
- err = ecode.AegisTranDisabled
- return
- }
- }
- return
- }
- /**
- * 不同order兼容性不同:
- * order=顺序,flow<->tran一对一
- * order=todo
- */
- func (s *Service) checkDirConflict(c context.Context, d *net.Direction) (err error, msg string) {
- var (
- flowDir, tranDir []*net.Direction
- orderDes, conflictDes string
- )
- if d == nil {
- return
- }
- if flowDir, err = s.gorm.DirectionByFlowID(c, []int64{d.FlowID}, d.Direction); err != nil {
- log.Error("checkDirConflict s.gorm.DirectionByFlowID error(%v) direction(%+v)", err, d)
- return
- }
- flowDirLen := len(flowDir)
- for k, item := range flowDir {
- if item.ID != d.ID {
- continue
- }
- if k < flowDirLen-1 {
- flowDir = append(flowDir[:k], flowDir[k+1:]...)
- } else {
- flowDir = flowDir[:k]
- }
- flowDirLen--
- }
- if tranDir, err = s.gorm.DirectionByTransitionID(c, []int64{d.TransitionID}, d.Direction, true); err != nil {
- log.Error("checkDirConflict s.gorm.DirectionByTransitionID error(%v) direction(%+v)", err, d)
- return
- }
- tranDirLen := len(tranDir)
- for k, item := range tranDir {
- if item.ID != d.ID {
- continue
- }
- if k < tranDirLen-1 {
- tranDir = append(tranDir[:k], tranDir[k+1:]...)
- } else {
- tranDir = tranDir[:k]
- }
- tranDirLen--
- }
- //无任何已有线
- if flowDirLen == 0 && tranDirLen == 0 {
- return
- }
- if d.Order == net.DirOrderSequence {
- conflictDes = "节点或变迁已被绑定"
- } else {
- //不支持的顺序报错
- log.Error("checkDirConflict order(%d) is not supported! direction(%+v)", d.Order, d)
- err = ecode.RequestErr
- return
- }
- //顺序兼容性报错
- log.Error("checkDirConflict direction(%+v) not allowed!", d)
- err = ecode.AegisDirOrderConflict
- orderDes = net.DirOrderDesc[d.Order]
- msg = fmt.Sprintf(ecode.AegisDirOrderConflict.Message(), orderDes, conflictDes)
- return
- }
- //AddDirection .
- func (s *Service) AddDirection(c context.Context, uid int64, d *net.DirEditParam) (id int64, err error, msg string) {
- var (
- canUpdate bool
- )
- if canUpdate, err = s.beforeUpdate(c, d.NetID); err != nil {
- log.Error("AddDirection s.beforeUpdate error(%v)", err)
- return
- }
- if !canUpdate {
- log.Error("AddDirection can't update param(%+v)", d)
- return
- }
- if err, msg = s.checkDirectionUnique(c, d.NetID, d.FlowID, d.TransitionID, d.Direction); err != nil {
- return
- }
- if err = s.checkDirectionBindAvailable(c, d.FlowID, d.TransitionID); err != nil {
- return
- }
- dir := &net.Direction{
- NetID: d.NetID,
- FlowID: d.FlowID,
- TransitionID: d.TransitionID,
- Direction: d.Direction,
- Order: d.Order,
- Guard: d.Guard,
- Output: d.Output,
- UID: uid,
- }
- if err, msg = s.checkDirConflict(c, dir); err != nil {
- return
- }
- tx, err := s.gorm.BeginTx(c)
- if err != nil {
- log.Error("AddDirection s.gorm.BeginTx error(%v)", err)
- return
- }
- if err = s.gorm.DisableNet(c, tx, dir.NetID); err != nil {
- tx.Rollback()
- return
- }
- if err = s.gorm.AddItem(c, tx, dir); err != nil {
- tx.Rollback()
- return
- }
- if err = tx.Commit().Error; err != nil {
- log.Error("AddDirection tx.Commit error(%v)", err)
- return
- }
- id = d.ID
- //日志
- oper := &model.NetConfOper{
- OID: dir.ID,
- Action: model.LogNetActionNew,
- UID: dir.UID,
- NetID: dir.NetID,
- FlowID: dir.FlowID,
- TranID: dir.TransitionID,
- Diff: []string{
- model.LogFieldTemp(model.LogFieldDirection, net.DirDirectionDesc[dir.Direction], "", false),
- model.LogFieldTemp(model.LogFieldOrder, net.DirOrderDesc[dir.Order], "", false),
- model.LogFieldTemp(model.LogFieldGuard, dir.Guard, "", false),
- model.LogFieldTemp(model.LogFieldOutput, dir.Output, "", false),
- },
- }
- s.sendNetConfLog(c, model.LogTypeDirConf, oper)
- return
- }
- //UpdateDirection .
- func (s *Service) UpdateDirection(c context.Context, uid int64, d *net.DirEditParam) (err error, msg string) {
- var (
- old *net.Direction
- canUpdate, checkUnique, orderChanged bool
- updates = map[string]interface{}{}
- diff = []string{}
- )
- if old, err = s.gorm.DirectionByID(c, d.ID); err != nil {
- log.Error("UpdateDirection s.gorm.DirectionByID(%d) error(%v)", d.ID, err)
- return
- }
- if canUpdate, err = s.beforeUpdate(c, old.NetID); err != nil {
- log.Error("UpdateDirection s.beforeUpdate error(%v)", err)
- return
- }
- if !canUpdate {
- log.Error("UpdateDirection can't update param(%+v)", d)
- return
- }
- cp := *old
- nw := &cp
- if d.FlowID != old.FlowID {
- if err = s.checkDirectionBindAvailable(c, d.FlowID, 0); err != nil {
- return
- }
- checkUnique = true
- nw.FlowID = d.FlowID
- updates["flow_id"] = d.FlowID
- }
- if d.TransitionID != old.TransitionID {
- if err = s.checkDirectionBindAvailable(c, 0, d.TransitionID); err != nil {
- return
- }
- checkUnique = true
- nw.TransitionID = d.TransitionID
- updates["transition_id"] = d.TransitionID
- }
- if d.Direction != old.Direction {
- checkUnique = true
- diff = append(diff, model.LogFieldTemp(model.LogFieldDirection, net.DirDirectionDesc[nw.Direction], net.DirDirectionDesc[old.Direction], true))
- nw.Direction = d.Direction
- updates["direction"] = d.Direction
- }
- if checkUnique {
- if err, msg = s.checkDirectionUnique(c, nw.NetID, nw.FlowID, nw.TransitionID, nw.Direction); err != nil {
- return
- }
- }
- if d.Order != old.Order {
- diff = append(diff, model.LogFieldTemp(model.LogFieldOrder, net.DirOrderDesc[nw.Order], net.DirOrderDesc[old.Order], true))
- nw.Order = d.Order
- updates["order"] = d.Order
- orderChanged = true
- }
- //todo-- guard,output
- if checkUnique || orderChanged {
- if err, msg = s.checkDirConflict(c, nw); err != nil {
- return
- }
- }
- if len(updates) <= 0 {
- return
- }
- tx, err := s.gorm.BeginTx(c)
- if err != nil {
- log.Error("UpdateDirection s.gorm.BeginTx error(%v)", err)
- return
- }
- if err = s.gorm.DisableNet(c, tx, old.NetID); err != nil {
- tx.Rollback()
- return
- }
- if err = s.gorm.UpdateFields(c, tx, net.TableDirection, old.ID, updates); err != nil {
- tx.Rollback()
- return
- }
- if err = tx.Commit().Error; err != nil {
- log.Error("UpdateDirection tx.Commit error(%v)", err)
- return
- }
- s.delDirCache(c, old)
- //日志
- oper := &model.NetConfOper{
- OID: nw.ID,
- Action: model.LogNetActionUpdate,
- UID: nw.UID,
- NetID: nw.NetID,
- FlowID: nw.FlowID,
- TranID: nw.TransitionID,
- Diff: diff,
- }
- s.sendNetConfLog(c, model.LogTypeDirConf, oper)
- return
- }
- /**
- * isDirEnable 检查到下一步的可能性,由order&guard决定
- */
- func (s *Service) isDirEnable(dir *net.Direction) (enable bool) {
- if dir == nil {
- return
- }
- if (dir.Order != net.DirOrderOrSplit && dir.Order != net.DirOrderOrResultSplit) ||
- (dir.Order == net.DirOrderOrResultSplit && dir.Guard == "") {
- enable = true
- return
- }
- //todo--compute guard expression-v2
- return
- }
- /**
- * dispatchDirs 方向线是否可达下一步
- * 加入资源维度:若资源没有任何可达性如何办,这是配置错误--后期加入动态检查
- */
- func (s *Service) dispatchDirs(dirs []*net.Direction) (enableDir []*net.Direction) {
- var (
- enable bool
- )
- //对每个有向线, 过滤所有资源, 区分哪些资源可达
- enableDir = []*net.Direction{}
- for _, dir := range dirs {
- enable = s.isDirEnable(dir)
- if enable {
- enableDir = append(enableDir, dir)
- continue
- }
- }
- return
- }
- /**
- * fetchFlowNextEnableDirs 从flow出发,找到下一步变迁
- * 后期加入资源维度:若资源没有任何可达性如何办,这是配置错误--后期加入动态检查
- * 被应用在:
- * 1. 新节点查看下一步变迁是否需要创建分发任务;
- * 2. 审核提交后,通过flowid找到被触发的是哪个变迁(必须是同一个---后期加入动态检查);
- * 3. 通过flowid获取可用变迁的操作项;
- * todo -- 任务方存储了transitionid后,可以移除2+3逻辑
- */
- func (s *Service) fetchFlowNextEnableDirs(c context.Context, flowID int64) (enableDir []*net.Direction, err error) {
- var (
- list []*net.Direction
- )
- //找到以flow为起点的所有方向线
- if list, err = s.dirByFlow(c, []int64{flowID}, net.DirInput); err != nil {
- log.Error("fetchFlowNextEnableDirs s.dirByFlow(%d) error(%v)", flowID, err)
- return
- }
- if len(list) == 0 { //没配置下一步,正常情况
- return
- }
- if enableDir = s.dispatchDirs(list); len(enableDir) == 0 {
- err = ecode.AegisFlowNoEnableTran
- log.Error("fetchFlowNextEnableDirs s.dispatchDirs flowid(%v) no enable transition", flowID)
- }
- return
- }
- /**
- * fetchTranNextEnableDirs 从变迁出发,找到下一步flow
- * 后期加入资源维度
- */
- func (s *Service) fetchTranNextEnableDirs(c context.Context, tranID int64) (resultDir *net.Direction, err error) {
- var (
- list []*net.Direction
- enableDir []*net.Direction
- )
- if list, err = s.dirByTran(c, []int64{tranID}, net.DirOutput, true); err != nil {
- log.Error("fetchTranNextEnableDirs s.dirByTran(%d) error(%v)", tranID, err)
- return
- }
- if len(list) == 0 { //变迁后面没配置flow,为配置错误--后期都需要添加动态检查
- err = ecode.AegisTranNoFlow
- log.Error("fetchTranNextEnableDirs s.gorm.DirectionByTransitionID(%d) no flow", tranID)
- return
- }
- enableDir = s.dispatchDirs(list)
- if len(enableDir) == 0 { //变迁后面,没有任何可用flow,为配置错误---后期需添加动态检查
- err = ecode.AegisTranNoFlow
- log.Error("fetchTranNextEnableDirs transition(%d) has no enable flow", tranID)
- }
- //todo--允许变迁和节点的一对多对应吗?
- resultDir = enableDir[0]
- return
- }
- func (s *Service) beforeUpdate(c context.Context, netID int64) (ok bool, err error) {
- var (
- fr *net.FlowResource
- flowID []int64
- )
- if flowID, err = s.flowIDByNet(c, netID); err != nil {
- return
- }
- if len(flowID) > 0 {
- if fr, err = s.gorm.FRByFlow(c, flowID); err != nil {
- log.Error("beforeUpdate s.gorm.FRByFlow error(%v) netid(%d)", err, netID)
- return
- }
- }
- ok = fr == nil
- return
- }
|