package handler import ( "errors" "fmt" "net/http" "modelRT/database" "modelRT/diagram" "modelRT/log" "modelRT/model" "modelRT/network" "github.com/gin-gonic/gin" jsoniter "github.com/json-iterator/go" cmap "github.com/orcaman/concurrent-map/v2" "go.uber.org/zap" ) // CircuitDiagramUpdateHandler define circuit diagram update process API func CircuitDiagramUpdateHandler(c *gin.Context) { logger := log.GetLoggerInstance() pgClient := database.GetPostgresDBClient() var request network.CircuitDiagramUpdateRequest if err := c.ShouldBindJSON(&request); err != nil { logger.Error("unmarshal circuit diagram update info failed", zap.Error(err)) header := network.ResponseHeader{Status: http.StatusBadRequest, ErrMsg: err.Error()} resp := network.BasicResponse{ ResponseHeader: header, } c.JSON(http.StatusOK, resp) return } graph, err := diagram.GetGraphMap(request.PageID) if err != nil { logger.Error("get topologic data from set by pageID failed", zap.Error(err)) header := network.ResponseHeader{Status: http.StatusBadRequest, ErrMsg: err.Error()} resp := network.BasicResponse{ ResponseHeader: header, PayLoad: map[string]interface{}{ "page_id": request.PageID, }, } c.JSON(http.StatusOK, resp) return } // TODO 开启事务保证数据一致性 for _, topologicLink := range request.TopologicLinks { changeInfo, err := network.ParseUUID(topologicLink) if err != nil { logger.Error("format uuid from string failed", zap.Error(err)) header := network.ResponseHeader{Status: http.StatusBadRequest, ErrMsg: err.Error()} resp := network.BasicResponse{ ResponseHeader: header, PayLoad: map[string]interface{}{ "topologic_info": topologicLink, }, } c.JSON(http.StatusOK, resp) return } err = graph.UpdateEdge(changeInfo) if err != nil { logger.Error("update topologic info failed", zap.Any("topologic_info", topologicLink), zap.Error(err)) header := network.ResponseHeader{Status: http.StatusBadRequest, ErrMsg: err.Error()} resp := network.BasicResponse{ ResponseHeader: header, PayLoad: map[string]interface{}{ "topologic_info": topologicLink, }, } c.JSON(http.StatusOK, resp) return } // TODO 使用事务tx 代替 pg 全局 DB err = database.UpdateTopologicIntoDB(c, pgClient, request.PageID, changeInfo) if err != nil { // TODO 修改报错内容 logger.Error("update topologic info into DB failed", zap.Any("topologic_info", topologicLink), zap.Error(err)) header := network.ResponseHeader{Status: http.StatusBadRequest, ErrMsg: err.Error()} resp := network.BasicResponse{ ResponseHeader: header, PayLoad: map[string]interface{}{ "topologic_info": topologicLink, }, } c.JSON(http.StatusOK, resp) return } } for _, componentInfo := range request.ComponentInfos { parseStruct := model.SelectModelByType(componentInfo.ComponentType) if parseStruct == nil { err := fmt.Errorf("can not get component model by model type %d", componentInfo.ComponentType) logger.Error("get component model by model type failed", zap.String("uuid", componentInfo.UUID), zap.Int("component_type", componentInfo.ComponentType), zap.Error(err)) header := network.ResponseHeader{Status: http.StatusBadRequest, ErrMsg: err.Error()} resp := network.BasicResponse{ ResponseHeader: header, PayLoad: map[string]interface{}{ "uuid": componentInfo.UUID, "component_type": componentInfo.ComponentType, }, } c.JSON(http.StatusOK, resp) return } err := jsoniter.Unmarshal([]byte(componentInfo.Params), parseStruct) if err != nil { componentStructName := model.SelectModelNameByType(componentInfo.ComponentType) logger.Error("unmarshal component info by component struct failed", zap.String("component_struct_name", componentStructName), zap.Error(err)) header := network.ResponseHeader{Status: http.StatusBadRequest, ErrMsg: err.Error()} resp := network.BasicResponse{ ResponseHeader: header, PayLoad: map[string]interface{}{ "uuid": componentInfo.UUID, "component_type": componentInfo.ComponentType, "component_struct_name": componentStructName, }, } c.JSON(http.StatusOK, resp) return } result := pgClient.Where("uuid = ?", componentInfo.UUID).Save(parseStruct) if result.Error != nil || result.RowsAffected == 0 { err := result.Error if result.RowsAffected == 0 { err = errors.New("update component info by uuid failed,affected rows zero") } logger.Error("store component info into postgresDB failed", zap.Any("component_params", parseStruct), zap.Error(err)) header := network.ResponseHeader{Status: http.StatusBadRequest, ErrMsg: err.Error()} resp := network.BasicResponse{ ResponseHeader: header, PayLoad: map[string]interface{}{ "uuid": componentInfo.UUID, "component_params": parseStruct, }, } c.JSON(http.StatusOK, resp) return } parseMap := cmap.New[any]() err = parseMap.UnmarshalJSON([]byte(componentInfo.Params)) if err != nil { logger.Error("unmarshal component info by concurrent map failed", zap.String("component_params", componentInfo.Params), zap.Error(err)) header := network.ResponseHeader{Status: http.StatusBadRequest, ErrMsg: err.Error()} resp := network.BasicResponse{ ResponseHeader: header, PayLoad: map[string]interface{}{ "uuid": componentInfo.UUID, "component_params": componentInfo.Params, }, } c.JSON(http.StatusOK, resp) return } diagram.UpdateComponentMap(componentInfo.UUID, &parseMap) } resp := network.BasicResponse{ ResponseHeader: network.ResponseHeader{Status: http.StatusOK}, PayLoad: map[string]interface{}{ "page_id": request.PageID, }, } c.JSON(http.StatusOK, resp) }