Compare commits
2 Commits
b53746efcd
...
d8668afa46
| Author | SHA1 | Date |
|---|---|---|
|
|
d8668afa46 | |
|
|
f9824e2b24 |
|
|
@ -15,13 +15,14 @@ import (
|
|||
|
||||
// QueryAlertEventHandler define query alert event process API
|
||||
func QueryAlertEventHandler(c *gin.Context) {
|
||||
ctx := c.Request.Context()
|
||||
var targetLevel constants.AlertLevel
|
||||
|
||||
alertManger := alert.GetAlertMangerInstance()
|
||||
levelStr := c.Query("level")
|
||||
level, err := strconv.Atoi(levelStr)
|
||||
if err != nil {
|
||||
logger.Error(c, "convert alert level string to int failed", "error", err)
|
||||
logger.Error(ctx, "convert alert level string to int failed", "error", err)
|
||||
|
||||
resp := network.FailureResponse{
|
||||
Code: -1,
|
||||
|
|
|
|||
|
|
@ -19,15 +19,16 @@ import (
|
|||
|
||||
// ComponentAnchorReplaceHandler define component anchor point replace process API
|
||||
func ComponentAnchorReplaceHandler(c *gin.Context) {
|
||||
ctx := c.Request.Context()
|
||||
var uuid, anchorName string
|
||||
|
||||
pgClient := database.GetPostgresDBClient()
|
||||
cancelCtx, cancel := context.WithTimeout(c, 5*time.Second)
|
||||
cancelCtx, cancel := context.WithTimeout(ctx, 5*time.Second)
|
||||
defer cancel()
|
||||
|
||||
var request network.ComponetAnchorReplaceRequest
|
||||
if err := c.ShouldBindJSON(&request); err != nil {
|
||||
logger.Error(c, "unmarshal component anchor point replace info failed", "error", err)
|
||||
logger.Error(ctx, "unmarshal component anchor point replace info failed", "error", err)
|
||||
|
||||
resp := network.FailureResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
|
|
@ -42,7 +43,7 @@ func ComponentAnchorReplaceHandler(c *gin.Context) {
|
|||
var componentInfo orm.Component
|
||||
result := pgClient.WithContext(cancelCtx).Model(&orm.Component{}).Where("global_uuid = ?", uuid).Find(&componentInfo)
|
||||
if result.Error != nil {
|
||||
logger.Error(c, "query component detail info failed", "error", result.Error)
|
||||
logger.Error(ctx, "query component detail info failed", "error", result.Error)
|
||||
|
||||
resp := network.FailureResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
|
|
@ -54,7 +55,7 @@ func ComponentAnchorReplaceHandler(c *gin.Context) {
|
|||
|
||||
if result.RowsAffected == 0 {
|
||||
err := fmt.Errorf("query component detail info by uuid failed:%w", errcode.ErrQueryRowZero)
|
||||
logger.Error(c, "query component detail info from table is empty", "table_name", "component")
|
||||
logger.Error(ctx, "query component detail info from table is empty", "table_name", "component")
|
||||
|
||||
resp := network.FailureResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
|
|
|
|||
|
|
@ -2,6 +2,8 @@
|
|||
package handler
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"modelRT/constants"
|
||||
"modelRT/database"
|
||||
"modelRT/logger"
|
||||
|
|
@ -152,6 +154,8 @@ func validateBatchImportParams(params map[string]any) bool {
|
|||
func validateTestTaskParams(params map[string]any) bool {
|
||||
// Test task has optional parameters, all are valid
|
||||
// sleep_duration defaults to 60 seconds if not provided
|
||||
// TODO Add more validation logic for test task parameters if needed
|
||||
fmt.Println(params)
|
||||
return true
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -13,12 +13,13 @@ import (
|
|||
|
||||
// AttrDeleteHandler deletes a data attribute
|
||||
func AttrDeleteHandler(c *gin.Context) {
|
||||
ctx := c.Request.Context()
|
||||
var request network.AttrDeleteRequest
|
||||
clientToken := c.GetString("client_token")
|
||||
if clientToken == "" {
|
||||
err := common.ErrGetClientToken
|
||||
|
||||
logger.Error(c, "failed to get client token from context", "error", err)
|
||||
logger.Error(ctx, "failed to get client token from context", "error", err)
|
||||
c.JSON(http.StatusOK, network.FailureResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
Msg: err.Error(),
|
||||
|
|
@ -27,7 +28,7 @@ func AttrDeleteHandler(c *gin.Context) {
|
|||
}
|
||||
|
||||
if err := c.ShouldBindJSON(&request); err != nil {
|
||||
logger.Error(c, "failed to unmarshal attribute delete request", "error", err)
|
||||
logger.Error(ctx, "failed to unmarshal attribute delete request", "error", err)
|
||||
c.JSON(http.StatusOK, network.FailureResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
Msg: err.Error(),
|
||||
|
|
@ -35,9 +36,9 @@ func AttrDeleteHandler(c *gin.Context) {
|
|||
return
|
||||
}
|
||||
|
||||
rs := diagram.NewRedisString(c, request.AttrToken, clientToken, 10, true)
|
||||
rs := diagram.NewRedisString(ctx, request.AttrToken, clientToken, 10, true)
|
||||
if err := rs.GETDEL(request.AttrToken); err != nil {
|
||||
logger.Error(c, "failed to delete attribute from Redis", "attr_token", request.AttrToken, "error", err)
|
||||
logger.Error(ctx, "failed to delete attribute from Redis", "attr_token", request.AttrToken, "error", err)
|
||||
c.JSON(http.StatusOK, network.FailureResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
Msg: err.Error(),
|
||||
|
|
|
|||
|
|
@ -13,13 +13,14 @@ import (
|
|||
|
||||
// AttrGetHandler retrieves the value of a data attribute
|
||||
func AttrGetHandler(c *gin.Context) {
|
||||
ctx := c.Request.Context()
|
||||
var request network.AttrGetRequest
|
||||
|
||||
clientToken := c.GetString("client_token")
|
||||
if clientToken == "" {
|
||||
err := common.ErrGetClientToken
|
||||
|
||||
logger.Error(c, "failed to get client token from context", "error", err)
|
||||
logger.Error(ctx, "failed to get client token from context", "error", err)
|
||||
c.JSON(http.StatusOK, network.FailureResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
Msg: err.Error(),
|
||||
|
|
@ -28,7 +29,7 @@ func AttrGetHandler(c *gin.Context) {
|
|||
}
|
||||
|
||||
if err := c.ShouldBindJSON(&request); err != nil {
|
||||
logger.Error(c, "failed to unmarshal attribute get request", "error", err)
|
||||
logger.Error(ctx, "failed to unmarshal attribute get request", "error", err)
|
||||
c.JSON(http.StatusOK, network.FailureResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
Msg: err.Error(),
|
||||
|
|
@ -37,12 +38,12 @@ func AttrGetHandler(c *gin.Context) {
|
|||
}
|
||||
|
||||
pgClient := database.GetPostgresDBClient()
|
||||
tx := pgClient.Begin()
|
||||
tx := pgClient.WithContext(ctx).Begin()
|
||||
|
||||
attrModel, err := database.ParseAttrToken(c, tx, request.AttrToken, clientToken)
|
||||
attrModel, err := database.ParseAttrToken(ctx, tx, request.AttrToken, clientToken)
|
||||
if err != nil {
|
||||
tx.Rollback()
|
||||
logger.Error(c, "failed to parse attribute token", "attr_token", request.AttrToken, "error", err)
|
||||
logger.Error(ctx, "failed to parse attribute token", "attr_token", request.AttrToken, "error", err)
|
||||
c.JSON(http.StatusOK, network.FailureResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
Msg: err.Error(),
|
||||
|
|
|
|||
|
|
@ -13,13 +13,14 @@ import (
|
|||
|
||||
// AttrSetHandler sets the value of a data attribute
|
||||
func AttrSetHandler(c *gin.Context) {
|
||||
ctx := c.Request.Context()
|
||||
var request network.AttrSetRequest
|
||||
|
||||
clientToken := c.GetString("client_token")
|
||||
if clientToken == "" {
|
||||
err := common.ErrGetClientToken
|
||||
|
||||
logger.Error(c, "failed to get client token from context", "error", err)
|
||||
logger.Error(ctx, "failed to get client token from context", "error", err)
|
||||
c.JSON(http.StatusOK, network.FailureResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
Msg: err.Error(),
|
||||
|
|
@ -28,7 +29,7 @@ func AttrSetHandler(c *gin.Context) {
|
|||
}
|
||||
|
||||
if err := c.ShouldBindJSON(&request); err != nil {
|
||||
logger.Error(c, "failed to unmarshal attribute set request", "error", err)
|
||||
logger.Error(ctx, "failed to unmarshal attribute set request", "error", err)
|
||||
c.JSON(http.StatusOK, network.FailureResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
Msg: err.Error(),
|
||||
|
|
@ -37,9 +38,9 @@ func AttrSetHandler(c *gin.Context) {
|
|||
}
|
||||
|
||||
// The logic for handling Redis operations directly from the handler
|
||||
rs := diagram.NewRedisString(c, request.AttrToken, clientToken, 10, true)
|
||||
rs := diagram.NewRedisString(ctx, request.AttrToken, clientToken, 10, true)
|
||||
if err := rs.Set(request.AttrToken, request.AttrValue); err != nil {
|
||||
logger.Error(c, "failed to set attribute value in Redis", "attr_token", request.AttrToken, "error", err)
|
||||
logger.Error(ctx, "failed to set attribute value in Redis", "attr_token", request.AttrToken, "error", err)
|
||||
c.JSON(http.StatusOK, network.FailureResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
Msg: err.Error(),
|
||||
|
|
|
|||
|
|
@ -16,11 +16,12 @@ import (
|
|||
|
||||
// CircuitDiagramCreateHandler define circuit diagram create process API
|
||||
func CircuitDiagramCreateHandler(c *gin.Context) {
|
||||
ctx := c.Request.Context()
|
||||
pgClient := database.GetPostgresDBClient()
|
||||
|
||||
var request network.CircuitDiagramCreateRequest
|
||||
if err := c.ShouldBindJSON(&request); err != nil {
|
||||
logger.Error(c, "unmarshal circuit diagram create info failed", "error", err)
|
||||
logger.Error(ctx, "unmarshal circuit diagram create info failed", "error", err)
|
||||
|
||||
resp := network.FailureResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
|
|
@ -32,7 +33,7 @@ func CircuitDiagramCreateHandler(c *gin.Context) {
|
|||
|
||||
graph, err := diagram.GetGraphMap(request.PageID)
|
||||
if err != nil {
|
||||
logger.Error(c, "get topologic data from set by pageID failed", "error", err)
|
||||
logger.Error(ctx, "get topologic data from set by pageID failed", "error", err)
|
||||
|
||||
resp := network.FailureResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
|
|
@ -60,7 +61,7 @@ func CircuitDiagramCreateHandler(c *gin.Context) {
|
|||
err = fmt.Errorf("convert uuid from string failed:%w:%w", err1, err2)
|
||||
}
|
||||
|
||||
logger.Error(c, "format uuid from string failed", "error", err)
|
||||
logger.Error(ctx, "format uuid from string failed", "error", err)
|
||||
|
||||
resp := network.FailureResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
|
|
@ -78,13 +79,13 @@ func CircuitDiagramCreateHandler(c *gin.Context) {
|
|||
}
|
||||
|
||||
// open transaction
|
||||
tx := pgClient.Begin()
|
||||
tx := pgClient.WithContext(ctx).Begin()
|
||||
|
||||
err = database.CreateTopologicIntoDB(c, tx, request.PageID, topologicCreateInfos)
|
||||
err = database.CreateTopologicIntoDB(ctx, tx, request.PageID, topologicCreateInfos)
|
||||
if err != nil {
|
||||
tx.Rollback()
|
||||
|
||||
logger.Error(c, "create topologic info into DB failed", "topologic_info", topologicCreateInfos, "error", err)
|
||||
logger.Error(ctx, "create topologic info into DB failed", "topologic_info", topologicCreateInfos, "error", err)
|
||||
|
||||
resp := network.FailureResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
|
|
@ -102,11 +103,11 @@ func CircuitDiagramCreateHandler(c *gin.Context) {
|
|||
}
|
||||
|
||||
for index, info := range request.ComponentInfos {
|
||||
componentUUID, err := database.CreateComponentIntoDB(c, tx, info)
|
||||
componentUUID, err := database.CreateComponentIntoDB(ctx, tx, info)
|
||||
if err != nil {
|
||||
tx.Rollback()
|
||||
|
||||
logger.Error(c, "insert component info into DB failed", "error", err)
|
||||
logger.Error(ctx, "insert component info into DB failed", "error", err)
|
||||
|
||||
resp := network.FailureResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
|
|
@ -125,7 +126,7 @@ func CircuitDiagramCreateHandler(c *gin.Context) {
|
|||
// TODO 修复赋值问题
|
||||
component, err := network.ConvertComponentCreateInfosToComponents(info)
|
||||
if err != nil {
|
||||
logger.Error(c, "convert component params info failed", "component_info", info, "error", err)
|
||||
logger.Error(ctx, "convert component params info failed", "component_info", info, "error", err)
|
||||
|
||||
resp := network.FailureResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
|
|
|
|||
|
|
@ -21,11 +21,12 @@ import (
|
|||
|
||||
// CircuitDiagramDeleteHandler define circuit diagram delete process API
|
||||
func CircuitDiagramDeleteHandler(c *gin.Context) {
|
||||
ctx := c.Request.Context()
|
||||
pgClient := database.GetPostgresDBClient()
|
||||
|
||||
var request network.CircuitDiagramDeleteRequest
|
||||
if err := c.ShouldBindJSON(&request); err != nil {
|
||||
logger.Error(c, "unmarshal circuit diagram del info failed", "error", err)
|
||||
logger.Error(ctx, "unmarshal circuit diagram del info failed", "error", err)
|
||||
|
||||
resp := network.FailureResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
|
|
@ -37,7 +38,7 @@ func CircuitDiagramDeleteHandler(c *gin.Context) {
|
|||
|
||||
graph, err := diagram.GetGraphMap(request.PageID)
|
||||
if err != nil {
|
||||
logger.Error(c, "get topologic data from set by pageID failed", "error", err)
|
||||
logger.Error(ctx, "get topologic data from set by pageID failed", "error", err)
|
||||
|
||||
resp := network.FailureResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
|
|
@ -65,7 +66,7 @@ func CircuitDiagramDeleteHandler(c *gin.Context) {
|
|||
err = fmt.Errorf("convert uuid from string failed:%w:%w", err1, err2)
|
||||
}
|
||||
|
||||
logger.Error(c, "format uuid from string failed", "error", err)
|
||||
logger.Error(ctx, "format uuid from string failed", "error", err)
|
||||
|
||||
resp := network.FailureResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
|
|
@ -83,14 +84,14 @@ func CircuitDiagramDeleteHandler(c *gin.Context) {
|
|||
}
|
||||
|
||||
// open transaction
|
||||
tx := pgClient.Begin()
|
||||
tx := pgClient.WithContext(ctx).Begin()
|
||||
|
||||
for _, topologicDelInfo := range topologicDelInfos {
|
||||
err = database.DeleteTopologicIntoDB(c, tx, request.PageID, topologicDelInfo)
|
||||
err = database.DeleteTopologicIntoDB(ctx, tx, request.PageID, topologicDelInfo)
|
||||
if err != nil {
|
||||
tx.Rollback()
|
||||
|
||||
logger.Error(c, "delete topologic info into DB failed", "topologic_info", topologicDelInfo, "error", err)
|
||||
logger.Error(ctx, "delete topologic info into DB failed", "topologic_info", topologicDelInfo, "error", err)
|
||||
|
||||
resp := network.FailureResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
|
|
@ -107,7 +108,7 @@ func CircuitDiagramDeleteHandler(c *gin.Context) {
|
|||
if err != nil {
|
||||
tx.Rollback()
|
||||
|
||||
logger.Error(c, "delete topologic info failed", "topologic_info", topologicDelInfo, "error", err)
|
||||
logger.Error(ctx, "delete topologic info failed", "topologic_info", topologicDelInfo, "error", err)
|
||||
|
||||
resp := network.FailureResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
|
|
@ -126,14 +127,14 @@ func CircuitDiagramDeleteHandler(c *gin.Context) {
|
|||
}
|
||||
|
||||
for _, componentInfo := range request.ComponentInfos {
|
||||
cancelCtx, cancel := context.WithTimeout(c, 5*time.Second)
|
||||
cancelCtx, cancel := context.WithTimeout(ctx, 5*time.Second)
|
||||
defer cancel()
|
||||
|
||||
globalUUID, err := uuid.FromString(componentInfo.UUID)
|
||||
if err != nil {
|
||||
tx.Rollback()
|
||||
|
||||
logger.Error(c, "format uuid from string failed", "error", err)
|
||||
logger.Error(ctx, "format uuid from string failed", "error", err)
|
||||
|
||||
resp := network.FailureResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
|
|
@ -157,7 +158,7 @@ func CircuitDiagramDeleteHandler(c *gin.Context) {
|
|||
err = fmt.Errorf("%w:please check uuid conditions", errcode.ErrDeleteRowZero)
|
||||
}
|
||||
|
||||
logger.Error(c, "query component info into postgresDB failed", "component_global_uuid", componentInfo.UUID, "error", err)
|
||||
logger.Error(ctx, "query component info into postgresDB failed", "component_global_uuid", componentInfo.UUID, "error", err)
|
||||
|
||||
resp := network.FailureResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
|
|
@ -179,7 +180,7 @@ func CircuitDiagramDeleteHandler(c *gin.Context) {
|
|||
err = fmt.Errorf("%w:please check uuid conditions", errcode.ErrDeleteRowZero)
|
||||
}
|
||||
|
||||
logger.Error(c, "delete component info into postgresDB failed", "component_global_uuid", componentInfo.UUID, "error", err)
|
||||
logger.Error(ctx, "delete component info into postgresDB failed", "component_global_uuid", componentInfo.UUID, "error", err)
|
||||
|
||||
resp := network.FailureResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
|
|
|
|||
|
|
@ -24,11 +24,12 @@ import (
|
|||
// @Failure 400 {object} network.FailureResponse "request process failed"
|
||||
// @Router /model/diagram_load/{page_id} [get]
|
||||
func CircuitDiagramLoadHandler(c *gin.Context) {
|
||||
ctx := c.Request.Context()
|
||||
pgClient := database.GetPostgresDBClient()
|
||||
|
||||
pageID, err := strconv.ParseInt(c.Query("page_id"), 10, 64)
|
||||
if err != nil {
|
||||
logger.Error(c, "get pageID from url param failed", "error", err)
|
||||
logger.Error(ctx, "get pageID from url param failed", "error", err)
|
||||
|
||||
resp := network.FailureResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
|
|
@ -43,7 +44,7 @@ func CircuitDiagramLoadHandler(c *gin.Context) {
|
|||
|
||||
topologicInfo, err := diagram.GetGraphMap(pageID)
|
||||
if err != nil {
|
||||
logger.Error(c, "get topologic data from set by pageID failed", "error", err)
|
||||
logger.Error(ctx, "get topologic data from set by pageID failed", "error", err)
|
||||
|
||||
resp := network.FailureResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
|
|
@ -62,9 +63,9 @@ func CircuitDiagramLoadHandler(c *gin.Context) {
|
|||
componentParamMap := make(map[string]any)
|
||||
for _, VerticeLink := range topologicInfo.VerticeLinks {
|
||||
for _, componentUUID := range VerticeLink {
|
||||
component, err := database.QueryComponentByUUID(c, pgClient, componentUUID)
|
||||
component, err := database.QueryComponentByUUID(ctx, pgClient, componentUUID)
|
||||
if err != nil {
|
||||
logger.Error(c, "get component id info from DB by uuid failed", "error", err)
|
||||
logger.Error(ctx, "get component id info from DB by uuid failed", "error", err)
|
||||
|
||||
resp := network.FailureResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
|
|
@ -79,7 +80,7 @@ func CircuitDiagramLoadHandler(c *gin.Context) {
|
|||
|
||||
componentParams, err := diagram.GetComponentMap(component.GlobalUUID.String())
|
||||
if err != nil {
|
||||
logger.Error(c, "get component data from set by uuid failed", "error", err)
|
||||
logger.Error(ctx, "get component data from set by uuid failed", "error", err)
|
||||
|
||||
resp := network.FailureResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
|
|
@ -96,9 +97,9 @@ func CircuitDiagramLoadHandler(c *gin.Context) {
|
|||
}
|
||||
|
||||
rootVertexUUID := topologicInfo.RootVertex.String()
|
||||
rootComponent, err := database.QueryComponentByUUID(c, pgClient, topologicInfo.RootVertex)
|
||||
rootComponent, err := database.QueryComponentByUUID(ctx, pgClient, topologicInfo.RootVertex)
|
||||
if err != nil {
|
||||
logger.Error(c, "get component id info from DB by uuid failed", "error", err)
|
||||
logger.Error(ctx, "get component id info from DB by uuid failed", "error", err)
|
||||
|
||||
resp := network.FailureResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
|
|
@ -113,7 +114,7 @@ func CircuitDiagramLoadHandler(c *gin.Context) {
|
|||
|
||||
rootComponentParam, err := diagram.GetComponentMap(rootComponent.GlobalUUID.String())
|
||||
if err != nil {
|
||||
logger.Error(c, "get component data from set by uuid failed", "error", err)
|
||||
logger.Error(ctx, "get component data from set by uuid failed", "error", err)
|
||||
|
||||
resp := network.FailureResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
|
|
|
|||
|
|
@ -14,11 +14,12 @@ import (
|
|||
|
||||
// CircuitDiagramUpdateHandler define circuit diagram update process API
|
||||
func CircuitDiagramUpdateHandler(c *gin.Context) {
|
||||
ctx := c.Request.Context()
|
||||
pgClient := database.GetPostgresDBClient()
|
||||
|
||||
var request network.CircuitDiagramUpdateRequest
|
||||
if err := c.ShouldBindJSON(&request); err != nil {
|
||||
logger.Error(c, "unmarshal circuit diagram update info failed", "error", err)
|
||||
logger.Error(ctx, "unmarshal circuit diagram update info failed", "error", err)
|
||||
|
||||
resp := network.FailureResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
|
|
@ -30,7 +31,7 @@ func CircuitDiagramUpdateHandler(c *gin.Context) {
|
|||
|
||||
graph, err := diagram.GetGraphMap(request.PageID)
|
||||
if err != nil {
|
||||
logger.Error(c, "get topologic data from set by pageID failed", "error", err)
|
||||
logger.Error(ctx, "get topologic data from set by pageID failed", "error", err)
|
||||
|
||||
resp := network.FailureResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
|
|
@ -47,7 +48,7 @@ func CircuitDiagramUpdateHandler(c *gin.Context) {
|
|||
for _, topologicLink := range request.TopologicLinks {
|
||||
changeInfo, err := network.ParseUUID(topologicLink)
|
||||
if err != nil {
|
||||
logger.Error(c, "format uuid from string failed", "error", err)
|
||||
logger.Error(ctx, "format uuid from string failed", "error", err)
|
||||
|
||||
resp := network.FailureResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
|
|
@ -63,14 +64,14 @@ func CircuitDiagramUpdateHandler(c *gin.Context) {
|
|||
}
|
||||
|
||||
// open transaction
|
||||
tx := pgClient.Begin()
|
||||
tx := pgClient.WithContext(ctx).Begin()
|
||||
|
||||
for _, topologicChangeInfo := range topologicChangeInfos {
|
||||
err = database.UpdateTopologicIntoDB(c, tx, request.PageID, topologicChangeInfo)
|
||||
err = database.UpdateTopologicIntoDB(ctx, tx, request.PageID, topologicChangeInfo)
|
||||
if err != nil {
|
||||
tx.Rollback()
|
||||
|
||||
logger.Error(c, "update topologic info into DB failed", "topologic_info", topologicChangeInfo, "error", err)
|
||||
logger.Error(ctx, "update topologic info into DB failed", "topologic_info", topologicChangeInfo, "error", err)
|
||||
|
||||
resp := network.FailureResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
|
|
@ -87,7 +88,7 @@ func CircuitDiagramUpdateHandler(c *gin.Context) {
|
|||
if err != nil {
|
||||
tx.Rollback()
|
||||
|
||||
logger.Error(c, "update topologic info failed", "topologic_info", topologicChangeInfo, "error", err)
|
||||
logger.Error(ctx, "update topologic info failed", "topologic_info", topologicChangeInfo, "error", err)
|
||||
|
||||
resp := network.FailureResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
|
|
@ -102,9 +103,9 @@ func CircuitDiagramUpdateHandler(c *gin.Context) {
|
|||
}
|
||||
|
||||
for index, componentInfo := range request.ComponentInfos {
|
||||
componentUUID, err := database.UpdateComponentIntoDB(c, tx, componentInfo)
|
||||
componentUUID, err := database.UpdateComponentIntoDB(ctx, tx, componentInfo)
|
||||
if err != nil {
|
||||
logger.Error(c, "udpate component info into DB failed", "error", err)
|
||||
logger.Error(ctx, "udpate component info into DB failed", "error", err)
|
||||
|
||||
resp := network.FailureResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
|
|
@ -124,7 +125,7 @@ func CircuitDiagramUpdateHandler(c *gin.Context) {
|
|||
// TODO 修复赋值问题
|
||||
component, err := network.ConvertComponentUpdateInfosToComponents(info)
|
||||
if err != nil {
|
||||
logger.Error(c, "convert component params info failed", "component_info", info, "error", err)
|
||||
logger.Error(ctx, "convert component params info failed", "component_info", info, "error", err)
|
||||
|
||||
resp := network.FailureResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
|
|
|
|||
|
|
@ -22,12 +22,13 @@ import (
|
|||
|
||||
// ComponentAttributeQueryHandler define circuit diagram component attribute value query process API
|
||||
func ComponentAttributeQueryHandler(c *gin.Context) {
|
||||
ctx := c.Request.Context()
|
||||
pgClient := database.GetPostgresDBClient()
|
||||
|
||||
tokens := c.Param("tokens")
|
||||
if tokens == "" {
|
||||
err := fmt.Errorf("tokens is missing from the path")
|
||||
logger.Error(c, "query tokens from path failed", "error", err, "url", c.Request.RequestURI)
|
||||
logger.Error(ctx, "query tokens from path failed", "error", err, "url", c.Request.RequestURI)
|
||||
renderRespFailure(c, constants.RespCodeInvalidParams, err.Error(), nil)
|
||||
return
|
||||
}
|
||||
|
|
@ -54,10 +55,10 @@ func ComponentAttributeQueryHandler(c *gin.Context) {
|
|||
dbQueryMap := make(map[string][]cacheQueryItem)
|
||||
var secondaryQueryCount int
|
||||
for hSetKey, items := range cacheQueryMap {
|
||||
hset := diagram.NewRedisHash(c, hSetKey, 5000, false)
|
||||
hset := diagram.NewRedisHash(ctx, hSetKey, 5000, false)
|
||||
cacheData, err := hset.HGetAll()
|
||||
if err != nil {
|
||||
logger.Warn(c, "redis hgetall failed", "key", hSetKey, "err", err)
|
||||
logger.Warn(ctx, "redis hgetall failed", "key", hSetKey, "err", err)
|
||||
}
|
||||
for _, item := range items {
|
||||
if val, ok := cacheData[item.attributeName]; ok {
|
||||
|
|
@ -75,9 +76,9 @@ func ComponentAttributeQueryHandler(c *gin.Context) {
|
|||
return
|
||||
}
|
||||
|
||||
tx := pgClient.WithContext(c).Begin()
|
||||
tx := pgClient.WithContext(ctx).Begin()
|
||||
if tx.Error != nil {
|
||||
logger.Error(c, "begin postgres transaction failed", "error", tx.Error)
|
||||
logger.Error(ctx, "begin postgres transaction failed", "error", tx.Error)
|
||||
fillRemainingErrors(queryResults, tokenSlice, errcode.ErrBeginTxFailed)
|
||||
payload := genQueryRespPayload(queryResults, tokenSlice)
|
||||
renderRespFailure(c, constants.RespCodeServerError, "begin postgres database transaction failed", payload)
|
||||
|
|
@ -86,9 +87,9 @@ func ComponentAttributeQueryHandler(c *gin.Context) {
|
|||
defer tx.Rollback()
|
||||
|
||||
allCompTags := slices.Collect(maps.Keys(dbQueryMap))
|
||||
compModelMap, err := database.QueryComponentByCompTags(c, tx, allCompTags)
|
||||
compModelMap, err := database.QueryComponentByCompTags(ctx, tx, allCompTags)
|
||||
if err != nil {
|
||||
logger.Error(c, "query component info from postgres database failed", "error", err)
|
||||
logger.Error(ctx, "query component info from postgres database failed", "error", err)
|
||||
fillRemainingErrors(queryResults, tokenSlice, errcode.ErrDBQueryFailed)
|
||||
payload := genQueryRespPayload(queryResults, tokenSlice)
|
||||
renderRespFailure(c, constants.RespCodeServerError, "query component meta failed", payload)
|
||||
|
|
@ -116,7 +117,7 @@ func ComponentAttributeQueryHandler(c *gin.Context) {
|
|||
|
||||
tableNameMap, err := database.BatchGetProjectNames(tx, identifiers)
|
||||
if err != nil {
|
||||
logger.Error(c, "batch get table names from postgres database failed", "error", err)
|
||||
logger.Error(ctx, "batch get table names from postgres database failed", "error", err)
|
||||
fillRemainingErrors(queryResults, tokenSlice, errcode.ErrRetrieveFailed)
|
||||
payload := genQueryRespPayload(queryResults, tokenSlice)
|
||||
renderRespFailure(c, constants.RespCodeServerError, "batch get table names from postgres database failed", payload)
|
||||
|
|
@ -151,10 +152,11 @@ func ComponentAttributeQueryHandler(c *gin.Context) {
|
|||
}
|
||||
|
||||
if err := tx.Commit().Error; err != nil {
|
||||
logger.Warn(c, "postgres transaction commit failed, but returning scanned data", "error", err)
|
||||
logger.Warn(ctx, "postgres transaction commit failed, but returning scanned data", "error", err)
|
||||
} else {
|
||||
backfillCtx := context.WithoutCancel(ctx)
|
||||
for hKey, items := range redisSyncMap {
|
||||
go backfillRedis(c.Copy(), hKey, items)
|
||||
go backfillRedis(backfillCtx, hKey, items)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -18,10 +18,11 @@ import (
|
|||
|
||||
// ComponentAttributeUpdateHandler define circuit diagram component attribute value update process API
|
||||
func ComponentAttributeUpdateHandler(c *gin.Context) {
|
||||
ctx := c.Request.Context()
|
||||
pgClient := database.GetPostgresDBClient()
|
||||
var request network.ComponentAttributeUpdateInfo
|
||||
if err := c.ShouldBindJSON(&request); err != nil {
|
||||
logger.Error(c, "unmarshal request params failed", "error", err)
|
||||
logger.Error(ctx, "unmarshal request params failed", "error", err)
|
||||
renderRespFailure(c, constants.RespCodeInvalidParams, err.Error(), nil)
|
||||
return
|
||||
}
|
||||
|
|
@ -54,16 +55,16 @@ func ComponentAttributeUpdateHandler(c *gin.Context) {
|
|||
}
|
||||
|
||||
// open transaction
|
||||
tx := pgClient.WithContext(c).Begin()
|
||||
tx := pgClient.WithContext(ctx).Begin()
|
||||
if tx.Error != nil {
|
||||
logger.Error(c, "begin postgres transaction failed", "error", tx.Error)
|
||||
logger.Error(ctx, "begin postgres transaction failed", "error", tx.Error)
|
||||
renderRespFailure(c, constants.RespCodeServerError, "begin postgres transaction failed", nil)
|
||||
return
|
||||
}
|
||||
|
||||
compInfo, err := database.QueryComponentByCompTag(c, tx, attributeComponentTag)
|
||||
compInfo, err := database.QueryComponentByCompTag(ctx, tx, attributeComponentTag)
|
||||
if err != nil {
|
||||
logger.Error(c, "query component info by component tag failed", "error", err, "tag", attributeComponentTag)
|
||||
logger.Error(ctx, "query component info by component tag failed", "error", err, "tag", attributeComponentTag)
|
||||
|
||||
for _, attribute := range request.AttributeConfigs {
|
||||
if _, exists := updateResults[attribute.AttributeToken]; !exists {
|
||||
|
|
@ -139,7 +140,7 @@ func ComponentAttributeUpdateHandler(c *gin.Context) {
|
|||
}
|
||||
|
||||
for key, items := range redisUpdateMap {
|
||||
hset := diagram.NewRedisHash(c, key, 5000, false)
|
||||
hset := diagram.NewRedisHash(ctx, key, 5000, false)
|
||||
|
||||
fields := make(map[string]any, len(items))
|
||||
for _, item := range items {
|
||||
|
|
@ -147,7 +148,7 @@ func ComponentAttributeUpdateHandler(c *gin.Context) {
|
|||
}
|
||||
|
||||
if err := hset.SetRedisHashByMap(fields); err != nil {
|
||||
logger.Error(c, "batch sync redis failed", "hash_key", key, "error", err)
|
||||
logger.Error(ctx, "batch sync redis failed", "hash_key", key, "error", err)
|
||||
|
||||
for _, item := range items {
|
||||
if _, exists := updateResults[item.token]; exists {
|
||||
|
|
|
|||
|
|
@ -41,11 +41,12 @@ var linkSetConfigs = map[int]linkSetConfig{
|
|||
|
||||
// DiagramNodeLinkHandler defines the diagram node link process api
|
||||
func DiagramNodeLinkHandler(c *gin.Context) {
|
||||
ctx := c.Request.Context()
|
||||
var request network.DiagramNodeLinkRequest
|
||||
clientToken := c.GetString("client_token")
|
||||
if clientToken == "" {
|
||||
err := common.ErrGetClientToken
|
||||
logger.Error(c, "failed to get client token from context", "error", err)
|
||||
logger.Error(ctx, "failed to get client token from context", "error", err)
|
||||
c.JSON(http.StatusOK, network.FailureResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
Msg: err.Error(),
|
||||
|
|
@ -54,7 +55,7 @@ func DiagramNodeLinkHandler(c *gin.Context) {
|
|||
}
|
||||
|
||||
if err := c.ShouldBindJSON(&request); err != nil {
|
||||
logger.Error(c, "failed to unmarshal diagram node process request", "error", err)
|
||||
logger.Error(ctx, "failed to unmarshal diagram node process request", "error", err)
|
||||
|
||||
c.JSON(http.StatusOK, network.FailureResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
|
|
@ -68,9 +69,9 @@ func DiagramNodeLinkHandler(c *gin.Context) {
|
|||
nodeID := request.NodeID
|
||||
nodeLevel := request.NodeLevel
|
||||
action := request.Action
|
||||
prevNodeInfo, currNodeInfo, err := database.QueryNodeInfoByID(c, pgClient, nodeID, nodeLevel)
|
||||
prevNodeInfo, currNodeInfo, err := database.QueryNodeInfoByID(ctx, 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)
|
||||
logger.Error(ctx, "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,
|
||||
|
|
@ -84,8 +85,8 @@ func DiagramNodeLinkHandler(c *gin.Context) {
|
|||
return
|
||||
}
|
||||
|
||||
prevLinkSet, currLinkSet := generateLinkSet(c, nodeLevel, prevNodeInfo)
|
||||
err = processLinkSetData(c, action, nodeLevel, prevLinkSet, currLinkSet, prevNodeInfo, currNodeInfo)
|
||||
prevLinkSet, currLinkSet := generateLinkSet(ctx, nodeLevel, prevNodeInfo)
|
||||
err = processLinkSetData(ctx, action, nodeLevel, prevLinkSet, currLinkSet, prevNodeInfo, currNodeInfo)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusOK, network.FailureResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
|
|
@ -99,7 +100,7 @@ func DiagramNodeLinkHandler(c *gin.Context) {
|
|||
return
|
||||
}
|
||||
|
||||
logger.Info(c, "process diagram node link success", "node_id", nodeID, "level", nodeLevel, "action", request.Action)
|
||||
logger.Info(ctx, "process diagram node link success", "node_id", nodeID, "level", nodeLevel, "action", request.Action)
|
||||
|
||||
c.JSON(http.StatusOK, network.SuccessResponse{
|
||||
Code: http.StatusOK,
|
||||
|
|
|
|||
|
|
@ -16,11 +16,12 @@ import (
|
|||
|
||||
// QueryHistoryDataHandler define query history data process API
|
||||
func QueryHistoryDataHandler(c *gin.Context) {
|
||||
ctx := c.Request.Context()
|
||||
token := c.Query("token")
|
||||
beginStr := c.Query("begin")
|
||||
begin, err := strconv.Atoi(beginStr)
|
||||
if err != nil {
|
||||
logger.Error(c, "convert begin param from string to int failed", "error", err)
|
||||
logger.Error(ctx, "convert begin param from string to int failed", "error", err)
|
||||
|
||||
resp := network.FailureResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
|
|
@ -31,7 +32,7 @@ func QueryHistoryDataHandler(c *gin.Context) {
|
|||
endStr := c.Query("end")
|
||||
end, err := strconv.Atoi(endStr)
|
||||
if err != nil {
|
||||
logger.Error(c, "convert end param from string to int failed", "error", err)
|
||||
logger.Error(ctx, "convert end param from string to int failed", "error", err)
|
||||
|
||||
resp := network.FailureResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
|
|
|
|||
|
|
@ -15,13 +15,14 @@ import (
|
|||
|
||||
// MeasurementGetHandler define measurement query API
|
||||
func MeasurementGetHandler(c *gin.Context) {
|
||||
ctx := c.Request.Context()
|
||||
var request network.MeasurementGetRequest
|
||||
|
||||
clientToken := c.GetString("client_token")
|
||||
if clientToken == "" {
|
||||
err := common.ErrGetClientToken
|
||||
|
||||
logger.Error(c, "failed to get client token from context", "error", err)
|
||||
logger.Error(ctx, "failed to get client token from context", "error", err)
|
||||
c.JSON(http.StatusOK, network.FailureResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
Msg: err.Error(),
|
||||
|
|
@ -30,7 +31,7 @@ func MeasurementGetHandler(c *gin.Context) {
|
|||
}
|
||||
|
||||
if err := c.ShouldBindJSON(&request); err != nil {
|
||||
logger.Error(c, "failed to unmarshal measurement get request", "error", err)
|
||||
logger.Error(ctx, "failed to unmarshal measurement get request", "error", err)
|
||||
c.JSON(http.StatusOK, network.FailureResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
Msg: err.Error(),
|
||||
|
|
@ -38,10 +39,10 @@ func MeasurementGetHandler(c *gin.Context) {
|
|||
return
|
||||
}
|
||||
|
||||
zset := diagram.NewRedisZSet(c, request.MeasurementToken, 0, false)
|
||||
zset := diagram.NewRedisZSet(ctx, request.MeasurementToken, 0, false)
|
||||
points, err := zset.ZRANGE(request.MeasurementToken, 0, -1)
|
||||
if err != nil {
|
||||
logger.Error(c, "failed to get measurement data from redis", "measurement_token", request.MeasurementToken, "error", err)
|
||||
logger.Error(ctx, "failed to get measurement data from redis", "measurement_token", request.MeasurementToken, "error", err)
|
||||
c.JSON(http.StatusOK, network.FailureResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
Msg: err.Error(),
|
||||
|
|
@ -54,9 +55,9 @@ func MeasurementGetHandler(c *gin.Context) {
|
|||
}
|
||||
|
||||
pgClient := database.GetPostgresDBClient()
|
||||
measurementInfo, err := database.QueryMeasurementByID(c, pgClient, request.MeasurementID)
|
||||
measurementInfo, err := database.QueryMeasurementByID(ctx, pgClient, request.MeasurementID)
|
||||
if err != nil {
|
||||
logger.Error(c, "failed to query measurement by id", "measurement_id", request.MeasurementID, "error", err)
|
||||
logger.Error(ctx, "failed to query measurement by id", "measurement_id", request.MeasurementID, "error", err)
|
||||
c.JSON(http.StatusOK, network.FailureResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
Msg: err.Error(),
|
||||
|
|
|
|||
|
|
@ -2,11 +2,12 @@
|
|||
package handler
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"modelRT/constants"
|
||||
"modelRT/logger"
|
||||
"modelRT/model"
|
||||
"modelRT/network"
|
||||
"net/http"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
|
@ -43,18 +44,18 @@ import (
|
|||
//
|
||||
// @Router /measurement/recommend [get]
|
||||
func MeasurementRecommendHandler(c *gin.Context) {
|
||||
ctx := c.Request.Context()
|
||||
var request network.MeasurementRecommendRequest
|
||||
|
||||
if err := c.ShouldBindQuery(&request); err != nil {
|
||||
logger.Error(c, "failed to bind measurement recommend request", "error", err)
|
||||
logger.Error(ctx, "failed to bind measurement recommend request", "error", err)
|
||||
c.JSON(http.StatusOK, network.FailureResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
Msg: err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
recommendResults := model.RedisSearchRecommend(c, request.Input)
|
||||
recommendResults := model.RedisSearchRecommend(ctx, request.Input)
|
||||
payload := network.MeasurementRecommendPayload{
|
||||
Input: request.Input,
|
||||
RecommendedList: make([]string, 0),
|
||||
|
|
@ -65,7 +66,7 @@ func MeasurementRecommendHandler(c *gin.Context) {
|
|||
for _, recommendResult := range orderedResults {
|
||||
if recommendResult.Err != nil {
|
||||
err := recommendResult.Err
|
||||
logger.Error(c, "failed to get recommend data from redis", "input", request.Input, "error", err)
|
||||
logger.Error(ctx, "failed to get recommend data from redis", "input", request.Input, "error", err)
|
||||
c.JSON(http.StatusOK, network.FailureResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
Msg: err.Error(),
|
||||
|
|
|
|||
|
|
@ -18,11 +18,12 @@ import (
|
|||
|
||||
// MeasurementLinkHandler defines the measurement link process api
|
||||
func MeasurementLinkHandler(c *gin.Context) {
|
||||
ctx := c.Request.Context()
|
||||
var request network.MeasurementLinkRequest
|
||||
clientToken := c.GetString("client_token")
|
||||
if clientToken == "" {
|
||||
err := common.ErrGetClientToken
|
||||
logger.Error(c, "failed to get client token from context", "error", err)
|
||||
logger.Error(ctx, "failed to get client token from context", "error", err)
|
||||
c.JSON(http.StatusOK, network.FailureResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
Msg: err.Error(),
|
||||
|
|
@ -31,7 +32,7 @@ func MeasurementLinkHandler(c *gin.Context) {
|
|||
}
|
||||
|
||||
if err := c.ShouldBindJSON(&request); err != nil {
|
||||
logger.Error(c, "failed to unmarshal measurement process request", "error", err)
|
||||
logger.Error(ctx, "failed to unmarshal measurement process request", "error", err)
|
||||
|
||||
c.JSON(http.StatusOK, network.FailureResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
|
|
@ -44,9 +45,9 @@ func MeasurementLinkHandler(c *gin.Context) {
|
|||
pgClient := database.GetPostgresDBClient()
|
||||
measurementID := request.MeasurementID
|
||||
action := request.Action
|
||||
measurementInfo, err := database.QueryMeasurementByID(c, pgClient, measurementID)
|
||||
measurementInfo, err := database.QueryMeasurementByID(ctx, pgClient, measurementID)
|
||||
if err != nil {
|
||||
logger.Error(c, "failed to query measurement info by measurement id from postgres", "meauserement_id", measurementID, "error", err)
|
||||
logger.Error(ctx, "failed to query measurement info by measurement id from postgres", "meauserement_id", measurementID, "error", err)
|
||||
|
||||
c.JSON(http.StatusOK, network.FailureResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
|
|
@ -59,9 +60,9 @@ func MeasurementLinkHandler(c *gin.Context) {
|
|||
return
|
||||
}
|
||||
|
||||
componentInfo, err := database.QueryComponentByUUID(c, pgClient, measurementInfo.ComponentUUID)
|
||||
componentInfo, err := database.QueryComponentByUUID(ctx, pgClient, measurementInfo.ComponentUUID)
|
||||
if err != nil {
|
||||
logger.Error(c, "failed to query component info by component uuid from postgres", "component_uuid", measurementInfo.ComponentUUID, "error", err)
|
||||
logger.Error(ctx, "failed to query component info by component uuid from postgres", "component_uuid", measurementInfo.ComponentUUID, "error", err)
|
||||
|
||||
c.JSON(http.StatusOK, network.FailureResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
|
|
@ -74,9 +75,9 @@ func MeasurementLinkHandler(c *gin.Context) {
|
|||
return
|
||||
}
|
||||
|
||||
allMeasSet := diagram.NewRedisSet(c, constants.RedisAllMeasTagSetKey, 0, false)
|
||||
allMeasSet := diagram.NewRedisSet(ctx, constants.RedisAllMeasTagSetKey, 0, false)
|
||||
compMeasLinkKey := fmt.Sprintf(constants.RedisSpecCompTagMeasSetKey, componentInfo.Tag)
|
||||
compMeasLinkSet := diagram.NewRedisSet(c, compMeasLinkKey, 0, false)
|
||||
compMeasLinkSet := diagram.NewRedisSet(ctx, compMeasLinkKey, 0, false)
|
||||
|
||||
switch action {
|
||||
case constants.SearchLinkAddAction:
|
||||
|
|
@ -84,18 +85,18 @@ func MeasurementLinkHandler(c *gin.Context) {
|
|||
err2 := compMeasLinkSet.SADD(measurementInfo.Tag)
|
||||
err = processActionError(err1, err2, action)
|
||||
if err != nil {
|
||||
logger.Error(c, "add measurement link process operation failed", "measurement_id", measurementID, "action", action, "error", err)
|
||||
logger.Error(ctx, "add measurement link process operation failed", "measurement_id", measurementID, "action", action, "error", err)
|
||||
}
|
||||
case constants.SearchLinkDelAction:
|
||||
err1 := allMeasSet.SREM(measurementInfo.Tag)
|
||||
err2 := compMeasLinkSet.SREM(measurementInfo.Tag)
|
||||
err = processActionError(err1, err2, action)
|
||||
if err != nil {
|
||||
logger.Error(c, "del measurement link process operation failed", "measurement_id", measurementID, "action", action, "error", err)
|
||||
logger.Error(ctx, "del measurement link process operation failed", "measurement_id", measurementID, "action", action, "error", err)
|
||||
}
|
||||
default:
|
||||
err = common.ErrUnsupportedLinkAction
|
||||
logger.Error(c, "unsupport measurement link process action", "measurement_id", measurementID, "action", action, "error", err)
|
||||
logger.Error(ctx, "unsupport measurement link process action", "measurement_id", measurementID, "action", action, "error", err)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
|
|
@ -110,7 +111,7 @@ func MeasurementLinkHandler(c *gin.Context) {
|
|||
return
|
||||
}
|
||||
|
||||
logger.Info(c, "process measurement link success", "measurement_id", measurementID, "action", request.Action)
|
||||
logger.Info(ctx, "process measurement link success", "measurement_id", measurementID, "action", request.Action)
|
||||
|
||||
c.JSON(http.StatusOK, network.SuccessResponse{
|
||||
Code: http.StatusOK,
|
||||
|
|
|
|||
|
|
@ -35,27 +35,28 @@ var pullUpgrader = websocket.Upgrader{
|
|||
// @Tags RealTime Component Websocket
|
||||
// @Router /monitors/data/realtime/stream/:clientID [get]
|
||||
func PullRealTimeDataHandler(c *gin.Context) {
|
||||
requestCtx := c.Request.Context()
|
||||
clientID := c.Param("clientID")
|
||||
if clientID == "" {
|
||||
err := fmt.Errorf("clientID is missing from the path")
|
||||
logger.Error(c, "query clientID from path failed", "error", err, "url", c.Request.RequestURI)
|
||||
logger.Error(requestCtx, "query clientID from path failed", "error", err, "url", c.Request.RequestURI)
|
||||
renderWSRespFailure(c, constants.RespCodeInvalidParams, err.Error(), nil)
|
||||
return
|
||||
}
|
||||
|
||||
conn, err := pullUpgrader.Upgrade(c.Writer, c.Request, nil)
|
||||
if err != nil {
|
||||
logger.Error(c, "upgrade http protocol to websocket protocol failed", "error", err)
|
||||
logger.Error(requestCtx, "upgrade http protocol to websocket protocol failed", "error", err)
|
||||
renderWSRespFailure(c, constants.RespCodeServerError, err.Error(), nil)
|
||||
return
|
||||
}
|
||||
defer conn.Close()
|
||||
|
||||
ctx, cancel := context.WithCancel(c.Request.Context())
|
||||
ctx, cancel := context.WithCancel(requestCtx)
|
||||
defer cancel()
|
||||
|
||||
conn.SetCloseHandler(func(code int, text string) error {
|
||||
logger.Info(c.Request.Context(), "websocket processor shutdown trigger",
|
||||
logger.Info(requestCtx, "websocket processor shutdown trigger",
|
||||
"clientID", clientID, "code", code, "reason", text)
|
||||
|
||||
// call cancel to notify other goroutines to stop working
|
||||
|
|
|
|||
|
|
@ -60,10 +60,11 @@ var wsUpgrader = websocket.Upgrader{
|
|||
//
|
||||
// @Router /data/realtime [get]
|
||||
func QueryRealTimeDataHandler(c *gin.Context) {
|
||||
ctx := c.Request.Context()
|
||||
var request network.RealTimeQueryRequest
|
||||
|
||||
if err := c.ShouldBindJSON(&request); err != nil {
|
||||
logger.Error(c, "failed to unmarshal real time query request", "error", err)
|
||||
logger.Error(ctx, "failed to unmarshal real time query request", "error", err)
|
||||
c.JSON(http.StatusOK, network.FailureResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
Msg: err.Error(),
|
||||
|
|
@ -73,7 +74,7 @@ func QueryRealTimeDataHandler(c *gin.Context) {
|
|||
|
||||
conn, err := wsUpgrader.Upgrade(c.Writer, c.Request, nil)
|
||||
if err != nil {
|
||||
logger.Error(c, "upgrade http protocol to websocket protocal failed", "error", err)
|
||||
logger.Error(ctx, "upgrade http protocol to websocket protocal failed", "error", err)
|
||||
return
|
||||
}
|
||||
defer conn.Close()
|
||||
|
|
@ -87,29 +88,29 @@ func QueryRealTimeDataHandler(c *gin.Context) {
|
|||
case data := <-transportChannel:
|
||||
respByte, err := jsoniter.Marshal(data)
|
||||
if err != nil {
|
||||
logger.Error(c, "marshal real time data to bytes failed", "error", err)
|
||||
logger.Error(ctx, "marshal real time data to bytes failed", "error", err)
|
||||
continue
|
||||
}
|
||||
|
||||
err = conn.WriteMessage(websocket.TextMessage, respByte)
|
||||
if err != nil {
|
||||
logger.Error(c, "write message to websocket connection failed", "error", err)
|
||||
logger.Error(ctx, "write message to websocket connection failed", "error", err)
|
||||
continue
|
||||
}
|
||||
case <-closeChannel:
|
||||
logger.Info(c, "data receiving goroutine has been closed")
|
||||
logger.Info(ctx, "data receiving goroutine has been closed")
|
||||
// TODO 优化时间控制
|
||||
deadline := time.Now().Add(5 * time.Second)
|
||||
err := conn.WriteControl(websocket.CloseMessage, websocket.FormatCloseMessage(websocket.CloseNormalClosure, "the session ended normally"), deadline)
|
||||
if err != nil {
|
||||
logger.Error(c, "sending close control message failed", "error", err)
|
||||
logger.Error(ctx, "sending close control message failed", "error", err)
|
||||
}
|
||||
// gracefully close session processing
|
||||
err = conn.Close()
|
||||
if err != nil {
|
||||
logger.Error(c, "websocket conn closed failed", "error", err)
|
||||
logger.Error(ctx, "websocket conn closed failed", "error", err)
|
||||
}
|
||||
logger.Info(c, "websocket connection closed successfully.")
|
||||
logger.Info(ctx, "websocket connection closed successfully.")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,9 +17,10 @@ var upgrader = websocket.Upgrader{
|
|||
|
||||
// RealTimeDataReceivehandler define real time data receive and process API
|
||||
func RealTimeDataReceivehandler(c *gin.Context) {
|
||||
ctx := c.Request.Context()
|
||||
conn, err := upgrader.Upgrade(c.Writer, c.Request, nil)
|
||||
if err != nil {
|
||||
logger.Error(c, "upgrade http protocol to websocket protocal failed", "error", err)
|
||||
logger.Error(ctx, "upgrade http protocol to websocket protocal failed", "error", err)
|
||||
return
|
||||
}
|
||||
defer conn.Close()
|
||||
|
|
@ -27,17 +28,17 @@ func RealTimeDataReceivehandler(c *gin.Context) {
|
|||
for {
|
||||
messageType, p, err := conn.ReadMessage()
|
||||
if err != nil {
|
||||
logger.Error(c, "read message from websocket connection failed", "error", err)
|
||||
logger.Error(ctx, "read message from websocket connection failed", "error", err)
|
||||
|
||||
respByte := processResponse(-1, "read message from websocket connection failed", nil)
|
||||
if len(respByte) == 0 {
|
||||
logger.Error(c, "process message from byte failed", "error", err)
|
||||
logger.Error(ctx, "process message from byte failed", "error", err)
|
||||
continue
|
||||
}
|
||||
|
||||
err = conn.WriteMessage(messageType, respByte)
|
||||
if err != nil {
|
||||
logger.Error(c, "write message to websocket connection failed", "error", err)
|
||||
logger.Error(ctx, "write message to websocket connection failed", "error", err)
|
||||
continue
|
||||
}
|
||||
continue
|
||||
|
|
@ -46,17 +47,17 @@ func RealTimeDataReceivehandler(c *gin.Context) {
|
|||
var request network.RealTimeDataReceiveRequest
|
||||
err = jsoniter.Unmarshal([]byte(p), &request)
|
||||
if err != nil {
|
||||
logger.Error(c, "unmarshal message from byte failed", "error", err)
|
||||
logger.Error(ctx, "unmarshal message from byte failed", "error", err)
|
||||
|
||||
respByte := processResponse(-1, "unmarshal message from byte failed", nil)
|
||||
if len(respByte) == 0 {
|
||||
logger.Error(c, "process message from byte failed", "error", err)
|
||||
logger.Error(ctx, "process message from byte failed", "error", err)
|
||||
continue
|
||||
}
|
||||
|
||||
err = conn.WriteMessage(messageType, respByte)
|
||||
if err != nil {
|
||||
logger.Error(c, "write message to websocket connection failed", "error", err)
|
||||
logger.Error(ctx, "write message to websocket connection failed", "error", err)
|
||||
continue
|
||||
}
|
||||
continue
|
||||
|
|
@ -70,13 +71,13 @@ func RealTimeDataReceivehandler(c *gin.Context) {
|
|||
}
|
||||
respByte := processResponse(0, "success", payload)
|
||||
if len(respByte) == 0 {
|
||||
logger.Error(c, "process message from byte failed", "error", err)
|
||||
logger.Error(ctx, "process message from byte failed", "error", err)
|
||||
continue
|
||||
}
|
||||
|
||||
err = conn.WriteMessage(messageType, respByte)
|
||||
if err != nil {
|
||||
logger.Error(c, "write message to websocket connection failed", "error", err)
|
||||
logger.Error(ctx, "write message to websocket connection failed", "error", err)
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -77,12 +77,13 @@ func init() {
|
|||
//
|
||||
// @Router /monitors/data/subscriptions [post]
|
||||
func RealTimeSubHandler(c *gin.Context) {
|
||||
ctx := c.Request.Context()
|
||||
var request network.RealTimeSubRequest
|
||||
var subAction string
|
||||
var clientID string
|
||||
|
||||
if err := c.ShouldBindJSON(&request); err != nil {
|
||||
logger.Error(c, "failed to unmarshal real time query request", "error", err)
|
||||
logger.Error(ctx, "failed to unmarshal real time query request", "error", err)
|
||||
renderRespFailure(c, constants.RespCodeInvalidParams, err.Error(), nil)
|
||||
return
|
||||
}
|
||||
|
|
@ -91,7 +92,7 @@ func RealTimeSubHandler(c *gin.Context) {
|
|||
subAction = request.Action
|
||||
id, err := uuid.NewV4()
|
||||
if err != nil {
|
||||
logger.Error(c, "failed to generate client id", "error", err)
|
||||
logger.Error(ctx, "failed to generate client id", "error", err)
|
||||
renderRespFailure(c, constants.RespCodeInvalidParams, err.Error(), nil)
|
||||
return
|
||||
}
|
||||
|
|
@ -114,9 +115,9 @@ func RealTimeSubHandler(c *gin.Context) {
|
|||
|
||||
switch subAction {
|
||||
case constants.SubStartAction:
|
||||
results, err := globalSubState.CreateConfig(c, tx, clientID, request.Measurements)
|
||||
results, err := globalSubState.CreateConfig(ctx, tx, clientID, request.Measurements)
|
||||
if err != nil {
|
||||
logger.Error(c, "create real time data subscription config failed", "error", err)
|
||||
logger.Error(ctx, "create real time data subscription config failed", "error", err)
|
||||
renderRespFailure(c, constants.RespCodeFailed, err.Error(), network.RealTimeSubPayload{
|
||||
ClientID: clientID,
|
||||
TargetResults: results,
|
||||
|
|
@ -130,9 +131,9 @@ func RealTimeSubHandler(c *gin.Context) {
|
|||
})
|
||||
return
|
||||
case constants.SubStopAction:
|
||||
results, err := globalSubState.RemoveTargets(c, clientID, request.Measurements)
|
||||
results, err := globalSubState.RemoveTargets(ctx, clientID, request.Measurements)
|
||||
if err != nil {
|
||||
logger.Error(c, "remove target to real time data subscription config failed", "error", err)
|
||||
logger.Error(ctx, "remove target to real time data subscription config failed", "error", err)
|
||||
renderRespFailure(c, constants.RespCodeFailed, err.Error(), network.RealTimeSubPayload{
|
||||
ClientID: clientID,
|
||||
TargetResults: results,
|
||||
|
|
@ -146,9 +147,9 @@ func RealTimeSubHandler(c *gin.Context) {
|
|||
})
|
||||
return
|
||||
case constants.SubAppendAction:
|
||||
results, err := globalSubState.AppendTargets(c, tx, clientID, request.Measurements)
|
||||
results, err := globalSubState.AppendTargets(ctx, tx, clientID, request.Measurements)
|
||||
if err != nil {
|
||||
logger.Error(c, "append target to real time data subscription config failed", "error", err)
|
||||
logger.Error(ctx, "append target to real time data subscription config failed", "error", err)
|
||||
renderRespFailure(c, constants.RespCodeFailed, err.Error(), network.RealTimeSubPayload{
|
||||
ClientID: clientID,
|
||||
TargetResults: results,
|
||||
|
|
@ -162,9 +163,9 @@ func RealTimeSubHandler(c *gin.Context) {
|
|||
})
|
||||
return
|
||||
case constants.SubUpdateAction:
|
||||
results, err := globalSubState.UpdateTargets(c, tx, clientID, request.Measurements)
|
||||
results, err := globalSubState.UpdateTargets(ctx, tx, clientID, request.Measurements)
|
||||
if err != nil {
|
||||
logger.Error(c, "update target to real time data subscription config failed", "error", err)
|
||||
logger.Error(ctx, "update target to real time data subscription config failed", "error", err)
|
||||
renderRespFailure(c, constants.RespCodeFailed, err.Error(), network.RealTimeSubPayload{
|
||||
ClientID: clientID,
|
||||
TargetResults: results,
|
||||
|
|
@ -179,7 +180,7 @@ func RealTimeSubHandler(c *gin.Context) {
|
|||
return
|
||||
default:
|
||||
err := fmt.Errorf("%w: request action is %s", common.ErrUnsupportedSubAction, request.Action)
|
||||
logger.Error(c, "unsupported action of real time data subscription request", "error", err)
|
||||
logger.Error(ctx, "unsupported action of real time data subscription request", "error", err)
|
||||
requestTargetsCount := processRealTimeRequestCount(request.Measurements)
|
||||
results := processRealTimeRequestTargets(request.Measurements, requestTargetsCount, constants.CodeUnsupportSubOperation, err)
|
||||
renderRespFailure(c, constants.RespCodeInvalidParams, err.Error(), network.RealTimeSubPayload{
|
||||
|
|
|
|||
|
|
@ -18,6 +18,8 @@ type facade struct {
|
|||
_logger *zap.Logger
|
||||
}
|
||||
|
||||
const facadeCallerSkip = 2
|
||||
|
||||
// Debug define facade func of debug level log
|
||||
func Debug(ctx context.Context, msg string, kv ...any) {
|
||||
logFacade().log(ctx, zapcore.DebugLevel, msg, kv...)
|
||||
|
|
@ -39,12 +41,16 @@ func Error(ctx context.Context, msg string, kv ...any) {
|
|||
}
|
||||
|
||||
func (f *facade) log(ctx context.Context, lvl zapcore.Level, msg string, kv ...any) {
|
||||
f.logSkip(ctx, lvl, 0, msg, kv...)
|
||||
f.logSkip(ctx, lvl, 1, msg, kv...)
|
||||
}
|
||||
|
||||
func (f *facade) logSkip(ctx context.Context, lvl zapcore.Level, extraSkip int, msg string, kv ...any) {
|
||||
fields := makeLogFieldsSkip(ctx, extraSkip, kv...)
|
||||
ce := f._logger.Check(lvl, msg)
|
||||
logger := f._logger
|
||||
if extraSkip > 0 {
|
||||
logger = logger.WithOptions(zap.AddCallerSkip(extraSkip))
|
||||
}
|
||||
ce := logger.Check(lvl, msg)
|
||||
ce.Write(fields...)
|
||||
}
|
||||
|
||||
|
|
@ -66,7 +72,7 @@ func InfoSkip(ctx context.Context, extraSkip int, msg string, kv ...any) {
|
|||
func logFacade() *facade {
|
||||
fOnce.Do(func() {
|
||||
f = &facade{
|
||||
_logger: GetLoggerInstance(),
|
||||
_logger: GetLoggerInstance().WithOptions(zap.AddCallerSkip(facadeCallerSkip)),
|
||||
}
|
||||
})
|
||||
return f
|
||||
|
|
|
|||
|
|
@ -90,6 +90,6 @@ func (s *ShortAttrInfo) IsLocal() bool {
|
|||
}
|
||||
|
||||
// GetAttrValue define return the attribute value
|
||||
func (l *ShortAttrInfo) GetAttrValue() any {
|
||||
return l.AttrValue
|
||||
func (s *ShortAttrInfo) GetAttrValue() any {
|
||||
return s.AttrValue
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
// Package model define model struct of model runtime service
|
||||
package model
|
||||
|
||||
import (
|
||||
|
|
@ -7,11 +8,12 @@ import (
|
|||
|
||||
// SelectModelByType define select the data structure for parsing based on the input model type
|
||||
func SelectModelByType(modelType int) BasicModelInterface {
|
||||
if modelType == constants.BusbarType {
|
||||
switch modelType {
|
||||
case constants.BusbarType:
|
||||
return &orm.BusbarSection{}
|
||||
} else if modelType == constants.AsyncMotorType {
|
||||
case constants.AsyncMotorType:
|
||||
return &orm.AsyncMotor{}
|
||||
} else if modelType == constants.DemoType {
|
||||
case constants.DemoType:
|
||||
return &orm.Demo{}
|
||||
}
|
||||
return nil
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import (
|
|||
"fmt"
|
||||
"math"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"modelRT/constants"
|
||||
"modelRT/diagram"
|
||||
|
|
@ -16,6 +17,7 @@ import (
|
|||
"github.com/RediSearch/redisearch-go/v2/redisearch"
|
||||
redigo "github.com/gomodule/redigo/redis"
|
||||
"github.com/redis/go-redis/v9"
|
||||
"golang.org/x/sync/errgroup"
|
||||
)
|
||||
|
||||
// SearchResult define struct to store redis query recommend search result
|
||||
|
|
@ -36,12 +38,44 @@ func InitAutocompleterWithPool(pool *redigo.Pool) {
|
|||
ac = redisearch.NewAutocompleterFromPool(pool, constants.RedisSearchDictName)
|
||||
}
|
||||
|
||||
type recommendSearchJob func() SearchResult
|
||||
|
||||
func runRecommendSearches(ctx context.Context, logMsg string, filterCompNSPath bool, jobs ...recommendSearchJob) map[string]SearchResult {
|
||||
results := make(map[string]SearchResult)
|
||||
var mu sync.Mutex
|
||||
var group errgroup.Group
|
||||
|
||||
for _, job := range jobs {
|
||||
job := job
|
||||
group.Go(func() error {
|
||||
result := job()
|
||||
if result.Err != nil {
|
||||
return fmt.Errorf("%s: %w", result.RecommendType, result.Err)
|
||||
}
|
||||
|
||||
if filterCompNSPath && result.RecommendType == constants.CompNSPathRecommendHierarchyType {
|
||||
result.QueryDatas = filterLocalNSPathResults(result.QueryDatas)
|
||||
}
|
||||
|
||||
mu.Lock()
|
||||
results[result.RecommendType.String()] = result
|
||||
mu.Unlock()
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
if err := group.Wait(); err != nil {
|
||||
logger.Error(ctx, logMsg, "error", err)
|
||||
}
|
||||
return results
|
||||
}
|
||||
|
||||
// levelOneRedisSearch 处理第一段输入的搜索, 例如 grid 或本地 nspath。
|
||||
func levelOneRedisSearch(ctx context.Context, rdb *redis.Client, hierarchy constants.RecommendHierarchyType, recommendLenType string, searchInput string, searchRedisKey string, fanInChan chan SearchResult) {
|
||||
func levelOneRedisSearch(ctx context.Context, rdb *redis.Client, hierarchy constants.RecommendHierarchyType, recommendLenType string, searchInput string, searchRedisKey string) (result SearchResult) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
logger.Error(ctx, "searchFunc panicked", "panic", r)
|
||||
fanInChan <- SearchResult{
|
||||
result = SearchResult{
|
||||
RecommendType: hierarchy,
|
||||
QueryDatas: nil,
|
||||
IsFuzzy: false,
|
||||
|
|
@ -54,64 +88,59 @@ func levelOneRedisSearch(ctx context.Context, rdb *redis.Client, hierarchy const
|
|||
if err != nil {
|
||||
logger.Error(ctx, "redis membership check failed", "key", searchRedisKey, "member", searchInput, "op", "SIsMember", "error", err)
|
||||
|
||||
fanInChan <- SearchResult{
|
||||
return SearchResult{
|
||||
RecommendType: hierarchy,
|
||||
QueryDatas: nil,
|
||||
IsFuzzy: false,
|
||||
Err: err,
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// the input key is the complete hierarchical value
|
||||
if exists {
|
||||
fanInChan <- SearchResult{
|
||||
return SearchResult{
|
||||
RecommendType: hierarchy,
|
||||
QueryDatas: []string{"."},
|
||||
IsFuzzy: false,
|
||||
Err: nil,
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// process fuzzy search result
|
||||
recommends, offset, err := runFuzzySearch(ctx, rdb, searchInput, "", hierarchy, recommendLenType)
|
||||
if err != nil {
|
||||
logger.Error(ctx, fmt.Sprintf("fuzzy search failed for %s hierarchical", util.GetLevelStrByRdsKey(searchRedisKey)), "search_input", searchInput, "error", err)
|
||||
fanInChan <- SearchResult{
|
||||
return SearchResult{
|
||||
RecommendType: hierarchy,
|
||||
QueryDatas: nil,
|
||||
IsFuzzy: false,
|
||||
Err: err,
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if len(recommends) > 0 {
|
||||
fanInChan <- SearchResult{
|
||||
return SearchResult{
|
||||
RecommendType: hierarchy,
|
||||
QueryDatas: recommends,
|
||||
IsFuzzy: true,
|
||||
Offset: offset,
|
||||
Err: nil,
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
recommends, err = fallbackAllCurrentLevel(ctx, rdb, hierarchy)
|
||||
if err != nil {
|
||||
logger.Error(ctx, "fallback all keys at current level failed", "hierarchy", hierarchy, "search_input", searchInput, "error", err)
|
||||
fanInChan <- SearchResult{
|
||||
return SearchResult{
|
||||
RecommendType: hierarchy,
|
||||
QueryDatas: nil,
|
||||
IsFuzzy: true,
|
||||
IsFallback: true,
|
||||
Err: err,
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
fanInChan <- SearchResult{
|
||||
return SearchResult{
|
||||
RecommendType: hierarchy,
|
||||
QueryDatas: recommends,
|
||||
IsFuzzy: true,
|
||||
|
|
@ -124,165 +153,102 @@ func levelOneRedisSearch(ctx context.Context, rdb *redis.Client, hierarchy const
|
|||
// RedisSearchRecommend define func of redis search by input string and return recommend results
|
||||
func RedisSearchRecommend(ctx context.Context, input string) map[string]SearchResult {
|
||||
rdb := diagram.GetRedisClientInstance()
|
||||
finalizeResults := func(results map[string]SearchResult) map[string]SearchResult {
|
||||
finalizeResults := func(normalizeInput string, results map[string]SearchResult) map[string]SearchResult {
|
||||
results = suppressFallbackResultsWhenConcreteHitExists(results)
|
||||
return normalizeRecommendResults(input, results)
|
||||
return normalizeRecommendResults(normalizeInput, results)
|
||||
}
|
||||
|
||||
if input == "" {
|
||||
fanInChan := make(chan SearchResult, 2)
|
||||
// return all grid tagname
|
||||
go getAllKeyByGridLevel(ctx, rdb, fanInChan)
|
||||
// return all component nspath
|
||||
go getAllKeyByNSPathLevel(ctx, rdb, fanInChan)
|
||||
results := make(map[string]SearchResult)
|
||||
for range 2 {
|
||||
result := <-fanInChan
|
||||
if result.Err != nil {
|
||||
logger.Error(ctx, "return all keys at the special level from redis failed", "recommend_type", result.RecommendType, "error", result.Err)
|
||||
continue
|
||||
}
|
||||
|
||||
if result.RecommendType == constants.CompNSPathRecommendHierarchyType {
|
||||
result.QueryDatas = filterLocalNSPathResults(result.QueryDatas)
|
||||
}
|
||||
results[result.RecommendType.String()] = result
|
||||
}
|
||||
|
||||
return finalizeResults(results)
|
||||
if input == "" || shouldFallbackToInitialRecommend(input) {
|
||||
results := runRecommendSearches(ctx, "return all keys at the special level from redis failed", true,
|
||||
func() SearchResult {
|
||||
return getAllKeyByGridLevel(ctx, rdb)
|
||||
},
|
||||
func() SearchResult {
|
||||
return getAllKeyByNSPathLevel(ctx, rdb)
|
||||
},
|
||||
)
|
||||
return finalizeResults("", results)
|
||||
}
|
||||
|
||||
inputSlice := strings.Split(input, ".")
|
||||
inputSliceLen := len(inputSlice)
|
||||
|
||||
fanInChan := make(chan SearchResult, 4)
|
||||
switch inputSliceLen {
|
||||
case 1:
|
||||
searchInput := inputSlice[0]
|
||||
// grid tagname search
|
||||
go levelOneRedisSearch(ctx, rdb, constants.GridRecommendHierarchyType, constants.FullRecommendLength, searchInput, constants.RedisAllGridSetKey, fanInChan)
|
||||
// component nspath search
|
||||
go levelOneRedisSearch(ctx, rdb, constants.CompNSPathRecommendHierarchyType, constants.IsLocalRecommendLength, searchInput, constants.RedisAllCompNSPathSetKey, fanInChan)
|
||||
|
||||
results := make(map[string]SearchResult)
|
||||
// TODO 后续根据支持的数据标识语法长度,进行值的变更
|
||||
for range 2 {
|
||||
result := <-fanInChan
|
||||
if result.Err != nil {
|
||||
logger.Error(ctx, "exec redis fuzzy search by key failed", "recommend_type", result.RecommendType, "error", result.Err)
|
||||
continue
|
||||
}
|
||||
|
||||
if result.RecommendType == constants.CompNSPathRecommendHierarchyType {
|
||||
result.QueryDatas = filterLocalNSPathResults(result.QueryDatas)
|
||||
}
|
||||
results[result.RecommendType.String()] = result
|
||||
}
|
||||
|
||||
return finalizeResults(results)
|
||||
results := runRecommendSearches(ctx, "exec redis fuzzy search by key failed", true,
|
||||
func() SearchResult {
|
||||
return levelOneRedisSearch(ctx, rdb, constants.GridRecommendHierarchyType, constants.FullRecommendLength, searchInput, constants.RedisAllGridSetKey)
|
||||
},
|
||||
func() SearchResult {
|
||||
return levelOneRedisSearch(ctx, rdb, constants.CompNSPathRecommendHierarchyType, constants.IsLocalRecommendLength, searchInput, constants.RedisAllCompNSPathSetKey)
|
||||
},
|
||||
)
|
||||
return finalizeResults(input, results)
|
||||
case 2:
|
||||
// zone tagname search
|
||||
go handleLevelFuzzySearch(ctx, rdb, constants.ZoneRecommendHierarchyType, constants.FullRecommendLength, constants.RedisAllZoneSetKey, inputSlice, fanInChan)
|
||||
// component tagname search
|
||||
go handleLevelFuzzySearch(ctx, rdb, constants.CompTagRecommendHierarchyType, constants.IsLocalRecommendLength, constants.RedisAllCompTagSetKey, inputSlice, fanInChan)
|
||||
// measurement tagname search by token4-token7 shorthand
|
||||
go handleNSPathMeasSearch(ctx, rdb, inputSlice, fanInChan)
|
||||
results := make(map[string]SearchResult)
|
||||
for range 3 {
|
||||
result := <-fanInChan
|
||||
if result.Err != nil {
|
||||
logger.Error(ctx, "query all keys at the special level from redis failed", "query_key", result.RecommendType, "error", result.Err)
|
||||
continue
|
||||
}
|
||||
results[result.RecommendType.String()] = result
|
||||
}
|
||||
|
||||
return finalizeResults(results)
|
||||
results := runRecommendSearches(ctx, "query all keys at the special level from redis failed", false,
|
||||
func() SearchResult {
|
||||
return handleLevelFuzzySearch(ctx, rdb, constants.ZoneRecommendHierarchyType, constants.FullRecommendLength, constants.RedisAllZoneSetKey, inputSlice)
|
||||
},
|
||||
func() SearchResult {
|
||||
return handleLevelFuzzySearch(ctx, rdb, constants.CompTagRecommendHierarchyType, constants.IsLocalRecommendLength, constants.RedisAllCompTagSetKey, inputSlice)
|
||||
},
|
||||
func() SearchResult {
|
||||
return handleNSPathMeasSearch(ctx, rdb, inputSlice)
|
||||
},
|
||||
)
|
||||
return finalizeResults(input, results)
|
||||
case 3:
|
||||
// station tanname search
|
||||
go handleLevelFuzzySearch(ctx, rdb, constants.StationRecommendHierarchyType, constants.FullRecommendLength, constants.RedisAllStationSetKey, inputSlice, fanInChan)
|
||||
// config search
|
||||
go handleLevelFuzzySearch(ctx, rdb, constants.ConfigRecommendHierarchyType, constants.IsLocalRecommendLength, constants.RedisAllConfigSetKey, inputSlice, fanInChan)
|
||||
|
||||
results := make(map[string]SearchResult)
|
||||
for range 2 {
|
||||
result := <-fanInChan
|
||||
if result.Err != nil {
|
||||
logger.Error(ctx, "query all keys at the special level from redis failed", "query_key", result.RecommendType, "error", result.Err)
|
||||
continue
|
||||
}
|
||||
results[result.RecommendType.String()] = result
|
||||
}
|
||||
|
||||
return finalizeResults(results)
|
||||
results := runRecommendSearches(ctx, "query all keys at the special level from redis failed", false,
|
||||
func() SearchResult {
|
||||
return handleLevelFuzzySearch(ctx, rdb, constants.StationRecommendHierarchyType, constants.FullRecommendLength, constants.RedisAllStationSetKey, inputSlice)
|
||||
},
|
||||
func() SearchResult {
|
||||
return handleLevelFuzzySearch(ctx, rdb, constants.ConfigRecommendHierarchyType, constants.IsLocalRecommendLength, constants.RedisAllConfigSetKey, inputSlice)
|
||||
},
|
||||
)
|
||||
return finalizeResults(input, results)
|
||||
case 4:
|
||||
// component nspath search
|
||||
go handleLevelFuzzySearch(ctx, rdb, constants.CompNSPathRecommendHierarchyType, constants.FullRecommendLength, constants.RedisAllCompNSPathSetKey, inputSlice, fanInChan)
|
||||
// measurement tagname search
|
||||
go handleLevelFuzzySearch(ctx, rdb, constants.MeasTagRecommendHierarchyType, constants.IsLocalRecommendLength, constants.RedisAllConfigSetKey, inputSlice, fanInChan)
|
||||
|
||||
results := make(map[string]SearchResult)
|
||||
for range 2 {
|
||||
result := <-fanInChan
|
||||
if result.Err != nil {
|
||||
logger.Error(ctx, "query all keys at the special level from redis failed", "query_key", result.RecommendType, "error", result.Err)
|
||||
continue
|
||||
}
|
||||
results[result.RecommendType.String()] = result
|
||||
}
|
||||
|
||||
return finalizeResults(results)
|
||||
results := runRecommendSearches(ctx, "query all keys at the special level from redis failed", false,
|
||||
func() SearchResult {
|
||||
return handleLevelFuzzySearch(ctx, rdb, constants.CompNSPathRecommendHierarchyType, constants.FullRecommendLength, constants.RedisAllCompNSPathSetKey, inputSlice)
|
||||
},
|
||||
func() SearchResult {
|
||||
return handleLevelFuzzySearch(ctx, rdb, constants.MeasTagRecommendHierarchyType, constants.IsLocalRecommendLength, constants.RedisAllConfigSetKey, inputSlice)
|
||||
},
|
||||
)
|
||||
return finalizeResults(input, results)
|
||||
case 5:
|
||||
// component tagname search
|
||||
go handleLevelFuzzySearch(ctx, rdb, constants.CompTagRecommendHierarchyType, constants.FullRecommendLength, constants.RedisAllCompTagSetKey, inputSlice, fanInChan)
|
||||
|
||||
results := make(map[string]SearchResult)
|
||||
for range 1 {
|
||||
result := <-fanInChan
|
||||
if result.Err != nil {
|
||||
logger.Error(ctx, "query all keys at the special level from redis failed", "query_key", result.RecommendType, "error", result.Err)
|
||||
continue
|
||||
}
|
||||
results[result.RecommendType.String()] = result
|
||||
}
|
||||
|
||||
return finalizeResults(results)
|
||||
results := runRecommendSearches(ctx, "query all keys at the special level from redis failed", false,
|
||||
func() SearchResult {
|
||||
return handleLevelFuzzySearch(ctx, rdb, constants.CompTagRecommendHierarchyType, constants.FullRecommendLength, constants.RedisAllCompTagSetKey, inputSlice)
|
||||
},
|
||||
)
|
||||
return finalizeResults(input, results)
|
||||
case 6:
|
||||
// config search
|
||||
go handleLevelFuzzySearch(ctx, rdb, constants.ConfigRecommendHierarchyType, constants.FullRecommendLength, constants.RedisAllConfigSetKey, inputSlice, fanInChan)
|
||||
|
||||
results := make(map[string]SearchResult)
|
||||
for range 1 {
|
||||
result := <-fanInChan
|
||||
if result.Err != nil {
|
||||
logger.Error(ctx, "query all keys at the special level from redis failed", "query_key", result.RecommendType, "error", result.Err)
|
||||
continue
|
||||
}
|
||||
results[result.RecommendType.String()] = result
|
||||
}
|
||||
|
||||
return finalizeResults(results)
|
||||
results := runRecommendSearches(ctx, "query all keys at the special level from redis failed", false,
|
||||
func() SearchResult {
|
||||
return handleLevelFuzzySearch(ctx, rdb, constants.ConfigRecommendHierarchyType, constants.FullRecommendLength, constants.RedisAllConfigSetKey, inputSlice)
|
||||
},
|
||||
)
|
||||
return finalizeResults(input, results)
|
||||
case 7:
|
||||
// measurement tagname search
|
||||
go handleLevelFuzzySearch(ctx, rdb, constants.MeasTagRecommendHierarchyType, constants.FullRecommendLength, constants.RedisAllMeasTagSetKey, inputSlice, fanInChan)
|
||||
|
||||
results := make(map[string]SearchResult)
|
||||
for range 1 {
|
||||
result := <-fanInChan
|
||||
if result.Err != nil {
|
||||
logger.Error(ctx, "query all keys at the special level from redis failed", "query_key", result.RecommendType, "error", result.Err)
|
||||
continue
|
||||
}
|
||||
results[result.RecommendType.String()] = result
|
||||
}
|
||||
|
||||
return finalizeResults(results)
|
||||
results := runRecommendSearches(ctx, "query all keys at the special level from redis failed", false,
|
||||
func() SearchResult {
|
||||
return handleLevelFuzzySearch(ctx, rdb, constants.MeasTagRecommendHierarchyType, constants.FullRecommendLength, constants.RedisAllMeasTagSetKey, inputSlice)
|
||||
},
|
||||
)
|
||||
return finalizeResults(input, results)
|
||||
default:
|
||||
logger.Error(ctx, "unsupport length of search input", "input_len", inputSliceLen)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func shouldFallbackToInitialRecommend(input string) bool {
|
||||
return strings.HasPrefix(input, ".")
|
||||
}
|
||||
|
||||
// suppressFallbackResultsWhenConcreteHitExists 有明确命中时丢弃兜底结果, 避免返回过宽推荐。
|
||||
func suppressFallbackResultsWhenConcreteHitExists(results map[string]SearchResult) map[string]SearchResult {
|
||||
hasConcreteHit := false
|
||||
|
|
@ -494,23 +460,22 @@ func getAllSetKeyByHierarchy(hierarchy constants.RecommendHierarchyType) (string
|
|||
}
|
||||
|
||||
// getAllKeyByGridLevel 返回所有 grid tag, 用于空输入时的初始推荐。
|
||||
func getAllKeyByGridLevel(ctx context.Context, rdb *redis.Client, fanInChan chan SearchResult) {
|
||||
func getAllKeyByGridLevel(ctx context.Context, rdb *redis.Client) SearchResult {
|
||||
setKey := constants.RedisAllGridSetKey
|
||||
hierarchy := constants.GridRecommendHierarchyType
|
||||
members, err := rdb.SMembers(ctx, setKey).Result()
|
||||
if err != nil && err != redigo.ErrNil {
|
||||
logger.Error(ctx, "get all members from redis by special key failed", "key", setKey, "op", "SMembers", "error", err)
|
||||
|
||||
fanInChan <- SearchResult{
|
||||
return SearchResult{
|
||||
RecommendType: hierarchy,
|
||||
QueryDatas: nil,
|
||||
IsFuzzy: false,
|
||||
Err: err,
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
fanInChan <- SearchResult{
|
||||
return SearchResult{
|
||||
RecommendType: hierarchy,
|
||||
QueryDatas: members,
|
||||
IsFuzzy: false,
|
||||
|
|
@ -519,23 +484,22 @@ func getAllKeyByGridLevel(ctx context.Context, rdb *redis.Client, fanInChan chan
|
|||
}
|
||||
|
||||
// getAllKeyByNSPathLevel 返回所有组件 nspath, 用于空输入时的初始推荐。
|
||||
func getAllKeyByNSPathLevel(ctx context.Context, rdb *redis.Client, fanInChan chan SearchResult) {
|
||||
func getAllKeyByNSPathLevel(ctx context.Context, rdb *redis.Client) SearchResult {
|
||||
queryKey := constants.RedisAllCompNSPathSetKey
|
||||
hierarchy := constants.CompNSPathRecommendHierarchyType
|
||||
members, err := rdb.SMembers(ctx, queryKey).Result()
|
||||
if err != nil && err != redigo.ErrNil {
|
||||
logger.Error(ctx, "get all members by special key failed", "key", queryKey, "op", "SMembers", "error", err)
|
||||
|
||||
fanInChan <- SearchResult{
|
||||
return SearchResult{
|
||||
RecommendType: hierarchy,
|
||||
QueryDatas: nil,
|
||||
IsFuzzy: false,
|
||||
Err: err,
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
fanInChan <- SearchResult{
|
||||
return SearchResult{
|
||||
RecommendType: hierarchy,
|
||||
QueryDatas: members,
|
||||
IsFuzzy: false,
|
||||
|
|
@ -611,7 +575,7 @@ func getSpecificKeyByLength(hierarchy constants.RecommendHierarchyType, keyPrefi
|
|||
}
|
||||
|
||||
// handleNSPathMeasSearch 处理 nspath.measurement 的简写搜索路径。
|
||||
func handleNSPathMeasSearch(ctx context.Context, rdb *redis.Client, inputSlice []string, fanInChan chan SearchResult) {
|
||||
func handleNSPathMeasSearch(ctx context.Context, rdb *redis.Client, inputSlice []string) SearchResult {
|
||||
hierarchy := constants.MeasTagRecommendHierarchyType
|
||||
nsPath := inputSlice[0]
|
||||
searchInput := inputSlice[1]
|
||||
|
|
@ -619,22 +583,20 @@ func handleNSPathMeasSearch(ctx context.Context, rdb *redis.Client, inputSlice [
|
|||
nsPathExists, err := rdb.SIsMember(ctx, constants.RedisAllCompNSPathSetKey, nsPath).Result()
|
||||
if err != nil {
|
||||
logger.Error(ctx, "check nspath exist from redis set failed", "key", constants.RedisAllCompNSPathSetKey, "nspath", nsPath, "error", err)
|
||||
fanInChan <- SearchResult{
|
||||
return SearchResult{
|
||||
RecommendType: hierarchy,
|
||||
QueryDatas: nil,
|
||||
IsFuzzy: false,
|
||||
Err: err,
|
||||
}
|
||||
return
|
||||
}
|
||||
if !nsPathExists {
|
||||
fanInChan <- SearchResult{
|
||||
return SearchResult{
|
||||
RecommendType: hierarchy,
|
||||
QueryDatas: []string{},
|
||||
IsFuzzy: false,
|
||||
Err: nil,
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
queryKey := fmt.Sprintf(constants.RedisSpecCompNSPathMeasSetKey, nsPath)
|
||||
|
|
@ -642,57 +604,52 @@ func handleNSPathMeasSearch(ctx context.Context, rdb *redis.Client, inputSlice [
|
|||
members, err := rdb.SMembers(ctx, queryKey).Result()
|
||||
if err != nil && err != redis.Nil {
|
||||
logger.Error(ctx, "query measurement tags by nspath failed", "key", queryKey, "nspath", nsPath, "error", err)
|
||||
fanInChan <- SearchResult{
|
||||
return SearchResult{
|
||||
RecommendType: hierarchy,
|
||||
QueryDatas: nil,
|
||||
IsFuzzy: false,
|
||||
Err: err,
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
fanInChan <- SearchResult{
|
||||
return SearchResult{
|
||||
RecommendType: hierarchy,
|
||||
QueryDatas: combineNSPathMeasResults(nsPath, members),
|
||||
IsFuzzy: false,
|
||||
Err: nil,
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
measTagExists, err := rdb.SIsMember(ctx, queryKey, searchInput).Result()
|
||||
if err != nil {
|
||||
logger.Error(ctx, "check measurement tag exist from nspath set failed", "key", queryKey, "meas_tag", searchInput, "error", err)
|
||||
fanInChan <- SearchResult{
|
||||
return SearchResult{
|
||||
RecommendType: hierarchy,
|
||||
QueryDatas: nil,
|
||||
IsFuzzy: false,
|
||||
Err: err,
|
||||
}
|
||||
return
|
||||
}
|
||||
if measTagExists {
|
||||
fanInChan <- SearchResult{
|
||||
return SearchResult{
|
||||
RecommendType: hierarchy,
|
||||
QueryDatas: []string{""},
|
||||
IsFuzzy: false,
|
||||
Err: nil,
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
recommends, offset, err := runNSPathMeasFuzzySearch(ctx, nsPath, searchInput)
|
||||
if err != nil {
|
||||
fanInChan <- SearchResult{
|
||||
return SearchResult{
|
||||
RecommendType: hierarchy,
|
||||
QueryDatas: nil,
|
||||
IsFuzzy: true,
|
||||
Err: err,
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
fanInChan <- SearchResult{
|
||||
return SearchResult{
|
||||
RecommendType: hierarchy,
|
||||
QueryDatas: recommends,
|
||||
IsFuzzy: true,
|
||||
|
|
@ -760,7 +717,7 @@ func splitLastToken(term string) (string, string) {
|
|||
}
|
||||
|
||||
// handleLevelFuzzySearch 处理第二层及以后层级的精确、模糊和兜底推荐。
|
||||
func handleLevelFuzzySearch(ctx context.Context, rdb *redis.Client, hierarchy constants.RecommendHierarchyType, recommendLenType string, redisSetKey string, inputSlice []string, fanInChan chan SearchResult) {
|
||||
func handleLevelFuzzySearch(ctx context.Context, rdb *redis.Client, hierarchy constants.RecommendHierarchyType, recommendLenType string, redisSetKey string, inputSlice []string) SearchResult {
|
||||
inputSliceLen := len(inputSlice)
|
||||
searchInputIndex := inputSliceLen - 1
|
||||
searchInput := inputSlice[searchInputIndex]
|
||||
|
|
@ -783,36 +740,33 @@ func handleLevelFuzzySearch(ctx context.Context, rdb *redis.Client, hierarchy co
|
|||
keyExists, err := rdb.SIsMember(ctx, redisSetKey, specificalKey).Result()
|
||||
if err != nil {
|
||||
logger.Error(ctx, "check key exist from redis set failed ", "key", redisSetKey, "error", err)
|
||||
fanInChan <- SearchResult{
|
||||
return SearchResult{
|
||||
RecommendType: hierarchy,
|
||||
QueryDatas: nil,
|
||||
IsFuzzy: false,
|
||||
Err: err,
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if !keyExists {
|
||||
fanInChan <- SearchResult{
|
||||
return SearchResult{
|
||||
RecommendType: hierarchy,
|
||||
QueryDatas: []string{},
|
||||
IsFuzzy: false,
|
||||
Err: nil,
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
members, err := queryMemberFromSpecificsLevel(ctx, rdb, hierarchy, specificalKey)
|
||||
if err != nil && err != redis.Nil {
|
||||
logger.Error(ctx, "query members from redis by special key failed", "key", specificalKey, "member", searchInput, "op", "SMember", "error", err)
|
||||
fanInChan <- SearchResult{
|
||||
return SearchResult{
|
||||
RecommendType: hierarchy,
|
||||
QueryDatas: nil,
|
||||
IsFuzzy: false,
|
||||
Err: err,
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
recommandResults := combineQueryResultByInput(hierarchy, recommendLenType, inputSlice, members)
|
||||
|
|
@ -838,25 +792,23 @@ func handleLevelFuzzySearch(ctx context.Context, rdb *redis.Client, hierarchy co
|
|||
}
|
||||
recommandResults = secondConfirmResults
|
||||
}
|
||||
fanInChan <- SearchResult{
|
||||
return SearchResult{
|
||||
RecommendType: hierarchy,
|
||||
QueryDatas: recommandResults,
|
||||
IsFuzzy: false,
|
||||
Err: nil,
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
keyExists, err := rdb.SIsMember(ctx, redisSetKey, searchInput).Result()
|
||||
if err != nil {
|
||||
logger.Error(ctx, "check key exist from redis set failed ", "key", redisSetKey, "error", err)
|
||||
fanInChan <- SearchResult{
|
||||
return SearchResult{
|
||||
RecommendType: hierarchy,
|
||||
QueryDatas: nil,
|
||||
IsFuzzy: false,
|
||||
Err: err,
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if keyExists {
|
||||
|
|
@ -867,26 +819,24 @@ func handleLevelFuzzySearch(ctx context.Context, rdb *redis.Client, hierarchy co
|
|||
QueryData = []string{"."}
|
||||
}
|
||||
|
||||
fanInChan <- SearchResult{
|
||||
return SearchResult{
|
||||
RecommendType: hierarchy,
|
||||
QueryDatas: QueryData,
|
||||
IsFuzzy: false,
|
||||
Err: nil,
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// start redis fuzzy search
|
||||
recommends, offset, err := runFuzzySearch(ctx, rdb, searchInput, searchPrefix, hierarchy, recommendLenType)
|
||||
if err != nil {
|
||||
logger.Error(ctx, "fuzzy search failed by hierarchy", "hierarchy", hierarchy, "search_input", searchInput, "error", err)
|
||||
fanInChan <- SearchResult{
|
||||
return SearchResult{
|
||||
RecommendType: hierarchy,
|
||||
QueryDatas: nil,
|
||||
IsFuzzy: false,
|
||||
Err: err,
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
isFallback := false
|
||||
|
|
@ -895,20 +845,19 @@ func handleLevelFuzzySearch(ctx context.Context, rdb *redis.Client, hierarchy co
|
|||
recommends, err = fallbackCurrentLevelByInput(ctx, rdb, hierarchy, inputSlice)
|
||||
if err != nil {
|
||||
logger.Error(ctx, "fallback all keys at current level failed", "hierarchy", hierarchy, "search_input", searchInput, "error", err)
|
||||
fanInChan <- SearchResult{
|
||||
return SearchResult{
|
||||
RecommendType: hierarchy,
|
||||
QueryDatas: nil,
|
||||
IsFuzzy: true,
|
||||
IsFallback: true,
|
||||
Err: err,
|
||||
}
|
||||
return
|
||||
}
|
||||
isFallback = true
|
||||
offset = 0
|
||||
}
|
||||
|
||||
fanInChan <- SearchResult{
|
||||
return SearchResult{
|
||||
RecommendType: hierarchy,
|
||||
QueryDatas: recommends,
|
||||
IsFuzzy: true,
|
||||
|
|
@ -992,7 +941,7 @@ func runFuzzySearch(ctx context.Context, rdb *redis.Client, searchInput string,
|
|||
}
|
||||
|
||||
if termHierarchyLen == compareHierarchyLen && termPrefix == comparePrefix && strings.HasPrefix(termLastPart, searchInput) {
|
||||
exists, err := fuzzyRecommendMemberExists(ctx, rdb, hierarchy, recommendLenType, comparePrefix, termLastPart)
|
||||
exists, err := fuzzyRecommendMemberExists(ctx, rdb, hierarchy, comparePrefix, termLastPart)
|
||||
if err != nil || !exists {
|
||||
logger.Info(ctx, "fuzzy recommend term not found in specific redis set",
|
||||
"hierarchy", hierarchy,
|
||||
|
|
@ -1034,8 +983,8 @@ func fuzzyRecommendOffset(searchPrefix string, searchInput string) int {
|
|||
}
|
||||
|
||||
// fuzzyRecommendMemberExists 校验模糊候选末级 token 是否存在于对应 Redis set。
|
||||
func fuzzyRecommendMemberExists(ctx context.Context, rdb *redis.Client, hierarchy constants.RecommendHierarchyType, recommendLenType string, comparePrefix string, termLastPart string) (bool, error) {
|
||||
setKey, ok := fuzzyRecommendMemberSetKey(hierarchy, recommendLenType, comparePrefix)
|
||||
func fuzzyRecommendMemberExists(ctx context.Context, rdb *redis.Client, hierarchy constants.RecommendHierarchyType, comparePrefix string, termLastPart string) (bool, error) {
|
||||
setKey, ok := fuzzyRecommendMemberSetKey(hierarchy, comparePrefix)
|
||||
if !ok {
|
||||
return true, nil
|
||||
}
|
||||
|
|
@ -1043,7 +992,7 @@ func fuzzyRecommendMemberExists(ctx context.Context, rdb *redis.Client, hierarch
|
|||
}
|
||||
|
||||
// fuzzyRecommendMemberSetKey 返回模糊候选校验时应使用的 Redis set key。
|
||||
func fuzzyRecommendMemberSetKey(hierarchy constants.RecommendHierarchyType, recommendLenType string, comparePrefix string) (string, bool) {
|
||||
func fuzzyRecommendMemberSetKey(hierarchy constants.RecommendHierarchyType, comparePrefix string) (string, bool) {
|
||||
switch hierarchy {
|
||||
case constants.GridRecommendHierarchyType:
|
||||
return constants.RedisAllGridSetKey, true
|
||||
|
|
|
|||
|
|
@ -1,6 +1,11 @@
|
|||
package model
|
||||
|
||||
import "testing"
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"modelRT/constants"
|
||||
)
|
||||
|
||||
func TestFuzzyRecommendOffsetUsesFullMatchedInput(t *testing.T) {
|
||||
tests := []struct {
|
||||
|
|
@ -38,3 +43,59 @@ func TestFuzzyRecommendOffsetUsesFullMatchedInput(t *testing.T) {
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestFallbackSpecificSetKey(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
hierarchy constants.RecommendHierarchyType
|
||||
inputSlice []string
|
||||
want string
|
||||
wantOK bool
|
||||
}{
|
||||
{
|
||||
name: "zone fallback uses grid specific set",
|
||||
hierarchy: constants.ZoneRecommendHierarchyType,
|
||||
inputSlice: []string{"grid000", "z"},
|
||||
want: fmt.Sprintf(constants.RedisSpecGridZoneSetKey, "grid000"),
|
||||
wantOK: true,
|
||||
},
|
||||
{
|
||||
name: "component tag fallback uses previous nspath token",
|
||||
hierarchy: constants.CompTagRecommendHierarchyType,
|
||||
inputSlice: []string{"grid000", "I"},
|
||||
want: fmt.Sprintf(constants.RedisSpecCompNSPathCompTagSetKey, "grid000"),
|
||||
wantOK: true,
|
||||
},
|
||||
{
|
||||
name: "measurement fallback skips config token and uses component tag",
|
||||
hierarchy: constants.MeasTagRecommendHierarchyType,
|
||||
inputSlice: []string{"nspath", "comp_tag", "config", "m"},
|
||||
want: fmt.Sprintf(constants.RedisSpecCompTagMeasSetKey, "comp_tag"),
|
||||
wantOK: true,
|
||||
},
|
||||
{
|
||||
name: "config fallback has no parent specific set",
|
||||
hierarchy: constants.ConfigRecommendHierarchyType,
|
||||
inputSlice: []string{"nspath", "comp_tag", ""},
|
||||
wantOK: false,
|
||||
},
|
||||
{
|
||||
name: "missing previous token",
|
||||
hierarchy: constants.ZoneRecommendHierarchyType,
|
||||
inputSlice: []string{"z"},
|
||||
wantOK: false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got, ok := fallbackSpecificSetKey(tt.hierarchy, tt.inputSlice)
|
||||
if ok != tt.wantOK {
|
||||
t.Fatalf("expected ok %t, got %t", tt.wantOK, ok)
|
||||
}
|
||||
if got != tt.want {
|
||||
t.Fatalf("expected key %q, got %q", tt.want, got)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,8 +6,8 @@ import (
|
|||
"time"
|
||||
)
|
||||
|
||||
// GenNanoTsStr define func to generate nanosecond timestamp string by current time
|
||||
func GenNanoTsStr() string {
|
||||
// GenNanoTSStr define func to generate nanosecond timestamp string by current time
|
||||
func GenNanoTSStr() string {
|
||||
now := time.Now()
|
||||
nanoseconds := now.UnixNano()
|
||||
timestampStr := strconv.FormatInt(nanoseconds, 10)
|
||||
|
|
|
|||
Loading…
Reference in New Issue