add diagram node link process api
This commit is contained in:
parent
f48807e5e5
commit
2a3852a246
|
|
@ -0,0 +1,80 @@
|
|||
// Package database define database operation functions
|
||||
package database
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"modelRT/orm"
|
||||
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
func queryFirstByID(ctx context.Context, tx *gorm.DB, id any, dest any) error {
|
||||
result := tx.WithContext(ctx).Where("id = ?", id).First(dest)
|
||||
return result.Error
|
||||
}
|
||||
|
||||
func queryFirstByTag(ctx context.Context, tx *gorm.DB, tagName any, dest any) error {
|
||||
result := tx.WithContext(ctx).Where("tagname = ?", tagName).First(dest)
|
||||
return result.Error
|
||||
}
|
||||
|
||||
// QueryNodeInfoByID return the result of query circuit diagram node info by id and level from postgresDB
|
||||
func QueryNodeInfoByID(ctx context.Context, tx *gorm.DB, id int64, level int) (orm.CircuitDiagramNodeInterface, orm.CircuitDiagramNodeInterface, error) {
|
||||
// 设置 Context 超时
|
||||
cancelCtx, cancel := context.WithTimeout(ctx, 5*time.Second)
|
||||
defer cancel()
|
||||
|
||||
var currentNodeInfo orm.CircuitDiagramNodeInterface
|
||||
var previousNodeInfo orm.CircuitDiagramNodeInterface
|
||||
var err error
|
||||
|
||||
switch level {
|
||||
case 0:
|
||||
var grid orm.Grid
|
||||
err = queryFirstByID(cancelCtx, tx, id, &grid)
|
||||
currentNodeInfo = grid
|
||||
case 1:
|
||||
// current:Zone,Previous:Grid
|
||||
var zone orm.Zone
|
||||
err = queryFirstByID(cancelCtx, tx, id, &zone)
|
||||
currentNodeInfo = zone
|
||||
if err == nil {
|
||||
var grid orm.Grid
|
||||
err = queryFirstByID(cancelCtx, tx, zone.GridID, &grid)
|
||||
previousNodeInfo = grid
|
||||
}
|
||||
case 2:
|
||||
// current:Station,Previous:Zone
|
||||
var station orm.Station
|
||||
err = queryFirstByID(cancelCtx, tx, id, &station)
|
||||
currentNodeInfo = station
|
||||
if err == nil {
|
||||
var zone orm.Zone
|
||||
err = queryFirstByID(cancelCtx, tx, station.ZoneID, &zone)
|
||||
previousNodeInfo = zone
|
||||
}
|
||||
case 3, 4:
|
||||
// current:Component, Previous:Station
|
||||
var component orm.Component
|
||||
err = queryFirstByID(cancelCtx, tx, id, &component)
|
||||
currentNodeInfo = component
|
||||
if err == nil {
|
||||
var station orm.Station
|
||||
err = queryFirstByTag(cancelCtx, tx, component.StationTag, &station)
|
||||
previousNodeInfo = station
|
||||
}
|
||||
case 5:
|
||||
// TODO[NONEED-ISSUE]暂无此层级增加或删除需求 #2
|
||||
return nil, nil, nil
|
||||
default:
|
||||
return nil, nil, fmt.Errorf("unsupported node level: %d", level)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
return previousNodeInfo, currentNodeInfo, nil
|
||||
}
|
||||
|
|
@ -121,7 +121,7 @@ func main() {
|
|||
var datas []float64
|
||||
if randomType {
|
||||
// 生成正常数据
|
||||
log.Printf("key:%s generate normal data type is %v\n", key, randomType)
|
||||
log.Printf("key:%s generate normal data\n", key)
|
||||
baseValue := measInfo.BaseValue
|
||||
changes := measInfo.Changes
|
||||
normalBase := changes[0]
|
||||
|
|
@ -140,7 +140,7 @@ func main() {
|
|||
log.Printf("// 验证结果: 所有值是否 >= %.2f或 <= %.2f %t\n", noramlMin, normalMax, allTrue)
|
||||
} else {
|
||||
// 生成异常数据
|
||||
log.Printf("key:%s generate abnormal data type is %v\n", key, randomType)
|
||||
log.Printf("key:%s generate abnormal data\n", key)
|
||||
var highMin, highBase float64
|
||||
var lowMin, lowBase float64
|
||||
var normalBase float64
|
||||
|
|
|
|||
|
|
@ -0,0 +1,188 @@
|
|||
// Package handler provides HTTP handlers for various endpoints.
|
||||
package handler
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"modelRT/constants"
|
||||
"modelRT/database"
|
||||
"modelRT/diagram"
|
||||
"modelRT/logger"
|
||||
"modelRT/network"
|
||||
"modelRT/orm"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
var linkSetConfigs = map[int]linkSetConfig{
|
||||
// grid hierarchy
|
||||
0: {CurrKey: constants.RedisAllGridSetKey, PrevIsNil: true},
|
||||
// zone hierarchy
|
||||
1: {CurrKey: constants.RedisAllZoneSetKey, PrevKeyTemplate: constants.RedisSpecGridZoneSetKey},
|
||||
// station hierarchy
|
||||
2: {CurrKey: constants.RedisAllStationSetKey, PrevKeyTemplate: constants.RedisSpecZoneStationSetKey},
|
||||
// component nspath hierarchy
|
||||
3: {CurrKey: constants.RedisAllCompNSPathSetKey, PrevKeyTemplate: constants.RedisSpecStationCompNSPATHSetKey},
|
||||
// component tag hierarchy
|
||||
4: {CurrKey: constants.RedisAllCompTagSetKey, PrevKeyTemplate: constants.RedisSpecStationCompTagSetKey},
|
||||
// config hierarchy
|
||||
5: {CurrKey: constants.RedisAllConfigSetKey, PrevIsNil: true},
|
||||
}
|
||||
|
||||
// DiagramNodeLinkHandler defines the diagram node link process api
|
||||
func DiagramNodeLinkHandler(c *gin.Context) {
|
||||
var request network.DiagramNodeLinkRequest
|
||||
clientToken := c.GetString("client_token")
|
||||
if clientToken == "" {
|
||||
err := constants.ErrGetClientToken
|
||||
logger.Error(c, "failed to get client token from context", "error", err)
|
||||
c.JSON(http.StatusOK, network.FailureResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
Msg: err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
if err := c.ShouldBindJSON(&request); err != nil {
|
||||
logger.Error(c, "failed to unmarshal diagram node process request", "error", err)
|
||||
|
||||
c.JSON(http.StatusOK, network.FailureResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
Msg: "invalid request body format: " + err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
var err error
|
||||
pgClient := database.GetPostgresDBClient()
|
||||
nodeID := request.NodeID
|
||||
nodeLevel := request.NodeLevel
|
||||
action := request.Action
|
||||
prevNodeInfo, currNodeInfo, err := database.QueryNodeInfoByID(c, pgClient, nodeID, nodeLevel)
|
||||
if err != nil {
|
||||
logger.Error(c, "failed to query diagram node info by nodeID and level from postgres", "node_id", nodeID, "level", nodeLevel, "error", err)
|
||||
|
||||
c.JSON(http.StatusOK, network.FailureResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
Msg: "failed to query measurement info record: " + err.Error(),
|
||||
Payload: map[string]any{
|
||||
"node_id": nodeID,
|
||||
"node_level": nodeLevel,
|
||||
"action": action,
|
||||
},
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
prevLinkSet, currLinkSet := generateLinkSet(c, nodeLevel, prevNodeInfo)
|
||||
err = processLinkSetData(c, action, nodeLevel, prevLinkSet, currLinkSet, prevNodeInfo, currNodeInfo)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusOK, network.FailureResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
Msg: err.Error(),
|
||||
Payload: map[string]any{
|
||||
"node_id": nodeID,
|
||||
"node_level": nodeLevel,
|
||||
"action": action,
|
||||
},
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
logger.Info(c, "process diagram node link success", "node_id", nodeID, "level", nodeLevel, "action", request.Action)
|
||||
|
||||
c.JSON(http.StatusOK, network.SuccessResponse{
|
||||
Code: http.StatusOK,
|
||||
Msg: "diagram node link process success",
|
||||
Payload: map[string]any{
|
||||
"node_id": nodeID,
|
||||
"node_level": nodeLevel,
|
||||
"action": action,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func generateLinkSet(ctx context.Context, level int, prevNodeInfo orm.CircuitDiagramNodeInterface) (*diagram.RedisSet, *diagram.RedisSet) {
|
||||
config, ok := linkSetConfigs[level]
|
||||
// level not supported
|
||||
if !ok {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
currLinkSet := diagram.NewRedisSet(ctx, config.CurrKey, 0, false)
|
||||
if config.PrevIsNil {
|
||||
return nil, currLinkSet
|
||||
}
|
||||
|
||||
prevLinkSetKey := fmt.Sprintf(config.PrevKeyTemplate, prevNodeInfo.GetTagName())
|
||||
prevLinkSet := diagram.NewRedisSet(ctx, prevLinkSetKey, 0, false)
|
||||
return prevLinkSet, currLinkSet
|
||||
}
|
||||
|
||||
func processLinkSetData(ctx context.Context, action string, level int, prevLinkSet, currLinkSet *diagram.RedisSet, prevNodeInfo, currNodeInfo orm.CircuitDiagramNodeInterface) error {
|
||||
var currMember string
|
||||
var prevMember string
|
||||
var err1, err2 error
|
||||
|
||||
switch level {
|
||||
case 0, 1, 2, 4:
|
||||
// grid、zone、station、component tag hierarchy
|
||||
currMember = currNodeInfo.GetTagName()
|
||||
if prevLinkSet != nil {
|
||||
prevMember = prevNodeInfo.GetTagName()
|
||||
}
|
||||
case 3:
|
||||
// component NSPath hierarchy
|
||||
currMember = currNodeInfo.GetNSPath()
|
||||
prevMember = prevNodeInfo.GetTagName()
|
||||
case 5:
|
||||
// TODO[NONEED-ISSUE]暂无此层级增加或删除需求 #2
|
||||
err := fmt.Errorf("currently hierarchy no need to add or delete this level: %d", level)
|
||||
logger.Error(ctx, "no need level for link process", "level", level, "action", action, "error", err)
|
||||
return nil
|
||||
default:
|
||||
err := fmt.Errorf("unsupported diagram node level: %d", level)
|
||||
logger.Error(ctx, "unsupport diagram node level for link process", "level", level, "action", action, "error", err)
|
||||
return err
|
||||
}
|
||||
|
||||
switch action {
|
||||
case constants.SearchLinkAddAction:
|
||||
err1 = currLinkSet.SADD(currMember)
|
||||
if prevLinkSet != nil {
|
||||
err2 = prevLinkSet.SADD(prevMember)
|
||||
}
|
||||
case constants.SearchLinkDelAction:
|
||||
err1 = currLinkSet.SREM(currMember)
|
||||
if prevLinkSet != nil {
|
||||
err2 = prevLinkSet.SREM(prevMember)
|
||||
}
|
||||
default:
|
||||
err := constants.ErrUnsupportedLinkAction
|
||||
logger.Error(ctx, "unsupport diagram node link process action", "action", action, "error", err)
|
||||
return err
|
||||
}
|
||||
return processDiagramLinkError(err1, err2, action)
|
||||
}
|
||||
|
||||
func processDiagramLinkError(err1, err2 error, action string) error {
|
||||
var err error
|
||||
if err1 != nil && err2 != nil {
|
||||
err = errors.Join(err1, err2)
|
||||
err = fmt.Errorf("process diagram node link failed, currLinkSet %s operation and prevLinkSet %s operation failed: %w", action, action, err)
|
||||
} else if err1 != nil {
|
||||
err = fmt.Errorf("process diagram node currLinkSet link failed: currLinkSet %s operation failed: %w", action, err1)
|
||||
} else {
|
||||
err = fmt.Errorf("process diagram node prevLinkSet link failed: prevLinkSet %s operation: %w", action, err2)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
type linkSetConfig struct {
|
||||
CurrKey string
|
||||
PrevKeyTemplate string
|
||||
PrevIsNil bool
|
||||
}
|
||||
|
|
@ -18,7 +18,6 @@ import (
|
|||
// MeasurementLinkHandler defines the measurement link process api
|
||||
func MeasurementLinkHandler(c *gin.Context) {
|
||||
var request network.MeasurementLinkRequest
|
||||
|
||||
clientToken := c.GetString("client_token")
|
||||
if clientToken == "" {
|
||||
err := constants.ErrGetClientToken
|
||||
|
|
@ -31,11 +30,11 @@ func MeasurementLinkHandler(c *gin.Context) {
|
|||
}
|
||||
|
||||
if err := c.ShouldBindJSON(&request); err != nil {
|
||||
logger.Error(c, "failed to unmarshal measurement create request", "error", err)
|
||||
logger.Error(c, "failed to unmarshal measurement process request", "error", err)
|
||||
|
||||
c.JSON(http.StatusOK, network.FailureResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
Msg: "Invalid request body format: " + err.Error(),
|
||||
Msg: "invalid request body format: " + err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
|
@ -49,7 +48,7 @@ func MeasurementLinkHandler(c *gin.Context) {
|
|||
logger.Error(c, "failed to query measurement info by measurement id from postgres", "meauserement_id", measurementID, "error", err)
|
||||
|
||||
c.JSON(http.StatusOK, network.FailureResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
Code: http.StatusBadRequest,
|
||||
Msg: "failed to query measurement info record: " + err.Error(),
|
||||
Payload: map[string]any{
|
||||
"id": measurementID,
|
||||
|
|
@ -64,7 +63,7 @@ func MeasurementLinkHandler(c *gin.Context) {
|
|||
logger.Error(c, "failed to query component info by component uuid from postgres", "component_uuid", measurementInfo.ComponentUUID, "error", err)
|
||||
|
||||
c.JSON(http.StatusOK, network.FailureResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
Code: http.StatusBadRequest,
|
||||
Msg: "failed to query component info record: " + err.Error(),
|
||||
Payload: map[string]any{
|
||||
"id": measurementID,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,22 @@
|
|||
// Package network define struct of network operation
|
||||
package network
|
||||
|
||||
// MeasurementLinkRequest defines the request payload for process an measurement link
|
||||
type MeasurementLinkRequest struct {
|
||||
// required: true
|
||||
MeasurementID int64 `json:"measurement_id" example:"1001"`
|
||||
// required: true
|
||||
// enum: [add, del]
|
||||
Action string `json:"action" example:"add"`
|
||||
}
|
||||
|
||||
// DiagramNodeLinkRequest defines the request payload for process an diagram node link
|
||||
type DiagramNodeLinkRequest struct {
|
||||
// required: true
|
||||
NodeID int64 `json:"node_id" example:"1001"`
|
||||
// required: true
|
||||
NodeLevel int `json:"node_level" example:"1"`
|
||||
// required: true
|
||||
// enum: [add, del]
|
||||
Action string `json:"action" example:"add"`
|
||||
}
|
||||
|
|
@ -7,15 +7,6 @@ type MeasurementGetRequest struct {
|
|||
MeasurementToken string `json:"token" example:"some-token"`
|
||||
}
|
||||
|
||||
// MeasurementLinkRequest defines the request payload for process an measurement link
|
||||
type MeasurementLinkRequest struct {
|
||||
// required: true
|
||||
MeasurementID int64 `json:"measurement_id" example:"1001"`
|
||||
// required: true
|
||||
// enum: [add, del]
|
||||
Action string `json:"action" example:"add"`
|
||||
}
|
||||
|
||||
// MeasurementRecommendRequest defines the request payload for an measurement recommend
|
||||
type MeasurementRecommendRequest struct {
|
||||
Input string `form:"input,omitempty" example:"grid1"`
|
||||
|
|
|
|||
|
|
@ -33,3 +33,13 @@ type Component struct {
|
|||
func (c *Component) TableName() string {
|
||||
return "component"
|
||||
}
|
||||
|
||||
// GetTagName define func to inplement CircuitDiagramNodeInterface interface
|
||||
func (c Component) GetTagName() string {
|
||||
return c.Tag
|
||||
}
|
||||
|
||||
// GetNSPath define func to inplement CircuitDiagramNodeInterface interface
|
||||
func (c Component) GetNSPath() string {
|
||||
return c.NsPath
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,3 +19,13 @@ type Grid struct {
|
|||
func (g *Grid) TableName() string {
|
||||
return "grid"
|
||||
}
|
||||
|
||||
// GetTagName define func to inplement CircuitDiagramNodeInterface interface
|
||||
func (g Grid) GetTagName() string {
|
||||
return g.TAGNAME
|
||||
}
|
||||
|
||||
// GetNSPath define func to inplement CircuitDiagramNodeInterface interface
|
||||
func (g Grid) GetNSPath() string {
|
||||
return ""
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,8 @@
|
|||
// Package orm define database data struct
|
||||
package orm
|
||||
|
||||
// CircuitDiagramNodeInterface define general node type interface
|
||||
type CircuitDiagramNodeInterface interface {
|
||||
GetTagName() string
|
||||
GetNSPath() string
|
||||
}
|
||||
|
|
@ -21,3 +21,13 @@ type Station struct {
|
|||
func (s *Station) TableName() string {
|
||||
return "station"
|
||||
}
|
||||
|
||||
// GetTagName define func to inplement CircuitDiagramNodeInterface interface
|
||||
func (s Station) GetTagName() string {
|
||||
return s.TAGNAME
|
||||
}
|
||||
|
||||
// GetNSPath define func to inplement CircuitDiagramNodeInterface interface
|
||||
func (s Station) GetNSPath() string {
|
||||
return ""
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,3 +20,13 @@ type Zone struct {
|
|||
func (z *Zone) TableName() string {
|
||||
return "zone"
|
||||
}
|
||||
|
||||
// GetTagName define func to inplement CircuitDiagramNodeInterface interface
|
||||
func (z Zone) GetTagName() string {
|
||||
return z.TAGNAME
|
||||
}
|
||||
|
||||
// GetNSPath define func to inplement CircuitDiagramNodeInterface interface
|
||||
func (z Zone) GetNSPath() string {
|
||||
return ""
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue