bilibili-backup/app/admin/main/aegis/service/net.go
2019-04-22 02:59:20 +00:00

274 lines
6.8 KiB
Go

package service
import (
"context"
"fmt"
"time"
"github.com/jinzhu/gorm"
"go-common/app/admin/main/aegis/model"
"go-common/app/admin/main/aegis/model/net"
"go-common/library/ecode"
"go-common/library/log"
)
//GetNetList .
func (s *Service) GetNetList(c context.Context, pm *net.ListNetParam) (result *net.ListNetRes, err error) {
var (
unames map[int64]string
)
if result, err = s.gorm.NetList(c, pm); err != nil {
return
}
if len(result.Result) == 0 {
return
}
//get username
uid := []int64{}
for _, item := range result.Result {
if item.UID > 0 {
uid = append(uid, item.UID)
}
}
if len(uid) == 0 {
return
}
if unames, err = s.http.GetUnames(c, uid); err != nil || len(unames) == 0 {
log.Error("GetNetList s.http.GetUnames error(%v) or empty uid(%+v)", err, uid)
err = nil
}
for _, item := range result.Result {
item.Username = unames[item.UID]
}
return
}
//GetNetByBusiness .
func (s *Service) GetNetByBusiness(c context.Context, businessID int64) (res map[int64]string, err error) {
var (
list []*net.Net
)
res = map[int64]string{}
if list, err = s.gorm.NetsByBusiness(c, []int64{businessID}, true); err != nil {
log.Error("GetNetByBusiness s.gorm.NetsByBusiness(%d) error(%v)", businessID, err)
return
}
for _, item := range list {
res[item.ID] = item.ChName
}
return
}
//ShowNet .
func (s *Service) ShowNet(c context.Context, id int64) (r *net.Net, err error) {
if r, err = s.gorm.NetByID(c, id); err != nil {
log.Error("ShowNet s.gorm.NetByID(%d) error(%v)", id, err)
}
return
}
func (s *Service) netCheckUnique(c context.Context, chName string) (err error, msg string) {
var exist *net.Net
if exist, err = s.gorm.NetByUnique(c, chName); err != nil && err != gorm.ErrRecordNotFound {
log.Error("netCheckUnique s.gorm.NetByID(%s) error(%v)", chName, err)
return
}
if exist != nil {
err = ecode.AegisUniqueAlreadyExist
msg = fmt.Sprintf(ecode.AegisUniqueAlreadyExist.Message(), "网", chName)
}
return
}
//AddNet .
func (s *Service) AddNet(c context.Context, n *net.Net) (id int64, err error, msg string) {
if err, msg = s.netCheckUnique(c, n.ChName); err != nil {
return
}
//网初建为禁用状态
n.DisableTime = time.Now()
if err = s.gorm.AddItem(c, nil, n); err != nil {
return
}
id = n.ID
//日志
oper := &model.NetConfOper{
OID: n.ID,
Action: model.LogNetActionNew,
UID: n.UID,
NetID: n.ID,
ChName: n.ChName,
FlowID: n.StartFlowID,
Diff: []string{model.LogFieldTemp(model.LogFieldPID, n.PID, 0, false)},
}
s.sendNetConfLog(c, model.LogTypeNetConf, oper)
return
}
//UpdateNet .
func (s *Service) UpdateNet(c context.Context, uid int64, n *net.NetEditParam) (err error, msg string) {
var (
old *net.Net
updates = map[string]interface{}{}
diff = []string{}
)
if old, err = s.gorm.NetByID(c, n.ID); err != nil {
log.Error("UpdateNet s.gorm.NetByID(%d) error(%v)", n.ID, err)
return
}
if n.ChName != old.ChName {
if err, msg = s.netCheckUnique(c, n.ChName); err != nil {
return
}
diff = append(diff, model.LogFieldTemp(model.LogFieldChName, n.ChName, old.ChName, true))
old.ChName = n.ChName
updates["ch_name"] = n.ChName
}
if n.Description != old.Description {
old.Description = n.Description
updates["description"] = n.Description
}
if err = s.gorm.UpdateFields(c, nil, net.TableNet, old.ID, updates); err != nil {
return
}
s.delNetCache(c, old)
//日志
if len(diff) == 0 {
return
}
oper := &model.NetConfOper{
OID: old.ID,
Action: model.LogNetActionUpdate,
UID: uid,
NetID: old.ID,
ChName: old.ChName,
FlowID: old.StartFlowID,
Diff: diff,
}
s.sendNetConfLog(c, model.LogTypeNetConf, oper)
return
}
//SwitchNet .
func (s *Service) SwitchNet(c context.Context, id int64, needDisable bool) (err error) {
var (
n *net.Net
action string
valid bool
)
if n, err = s.gorm.NetByID(c, id); err != nil {
log.Error("SwitchNet s.gorm.NetByID(%d) error(%v) needDisable(%v)", id, err, needDisable)
return
}
available := n.IsAvailable()
if available == !needDisable {
return
}
if needDisable {
n.DisableTime = time.Now()
action = model.LogNetActionDisable
} else {
if valid, err = s.checkNetValid(c, id); err != nil {
log.Error("SwitchNet s.checkNetValid error(%v) id(%d)", err, id)
return
}
if !valid {
log.Error("SwitchNet id(%d) isn't valid, can't be available", id)
err = ecode.AegisNetErr
return
}
n.DisableTime = net.Recovered
action = model.LogNetActionAvailable
}
if err = s.gorm.UpdateFields(c, nil, net.TableNet, id, map[string]interface{}{"disable_time": n.DisableTime}); err != nil {
return
}
s.delNetCache(c, n)
//日志
oper := &model.NetConfOper{
OID: n.ID,
Action: action,
UID: n.UID,
NetID: n.ID,
ChName: n.ChName,
FlowID: n.StartFlowID,
}
s.sendNetConfLog(c, model.LogTypeNetConf, oper)
return
}
//初步检查流程网的可用性:流转完整性
func (s *Service) checkNetValid(c context.Context, netID int64) (valid bool, err error) {
var (
n *net.Net
flow *net.Flow
dirs []*net.Direction
)
if n, err = s.netByID(c, netID); err != nil || n == nil || n.StartFlowID <= 0 {
log.Error("checkNetValid s.netByID(%d) error(%v)/not found/start_flow_id=0, net(%+v)", netID, err, n)
return
}
if flow, err = s.flowByID(c, n.StartFlowID); err != nil || flow == nil || !flow.IsAvailable() {
log.Error("checkNetValid s.flowByID(%d) error(%v)/flow not found/disabled, netid(%d), flow(%+v)", n.StartFlowID, err, netID, flow)
return
}
if dirs, err = s.gorm.DirectionByNet(c, netID); err != nil {
log.Error("checkNetValid s.gorm.DirectionByNet(%d) error(%v)", netID, err)
return
}
tranPrevMap := map[int64][]int64{}
tranNextMap := map[int64][]int64{}
flowPrevMap := map[int64][]int64{}
for _, item := range dirs {
if item.Direction == net.DirInput {
tranPrevMap[item.TransitionID] = append(tranPrevMap[item.TransitionID], item.FlowID)
continue
}
flowPrevMap[item.FlowID] = append(flowPrevMap[item.FlowID], item.TransitionID)
tranNextMap[item.TransitionID] = append(tranNextMap[item.TransitionID], item.FlowID)
}
/**
flow next empty/trans---dir=input
flow prev empty(start)/trans---dir=output
tran next flows---dir=output
tran prev flows---dir=input
*/
for flowID, trans := range flowPrevMap {
if len(trans) == 0 && flowID != n.StartFlowID {
log.Error("checkNetValid flow(%d) no previous transition", flowID)
return
}
}
for tranID, flows := range tranPrevMap {
prv := len(flows)
nxt := len(tranNextMap[tranID])
if prv == 0 || nxt == 0 {
log.Error("checkNetValid transition(%d) no prev(%d)/next(%d) flow", tranID, prv, nxt)
return
}
}
for tranID, flows := range tranNextMap {
prv := len(tranPrevMap[tranID])
nxt := len(flows)
if prv == 0 || nxt == 0 {
log.Error("checkNetValid transition(%d) no prev(%d)/next(%d) flow", tranID, prv, nxt)
return
}
}
valid = true
return
}