modelRT/handler/async_task_create_handler.go

153 lines
5.0 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// Package handler provides HTTP handlers for various endpoints.
package handler
import (
"modelRT/constants"
"modelRT/database"
"modelRT/logger"
"modelRT/network"
"modelRT/orm"
"modelRT/task"
"github.com/gin-gonic/gin"
)
// AsyncTaskCreateHandler handles creation of asynchronous tasks
// @Summary 创建异步任务
// @Description 创建新的异步任务并返回任务ID任务将被提交到队列等待处理
// @Tags AsyncTask
// @Accept json
// @Produce json
// @Param request body network.AsyncTaskCreateRequest true "任务创建请求"
// @Success 200 {object} network.SuccessResponse{payload=network.AsyncTaskCreateResponse} "任务创建成功"
// @Failure 400 {object} network.FailureResponse "请求参数错误"
// @Failure 500 {object} network.FailureResponse "服务器内部错误"
// @Router /task/async [post]
func AsyncTaskCreateHandler(c *gin.Context) {
ctx := c.Request.Context()
var request network.AsyncTaskCreateRequest
if err := c.ShouldBindJSON(&request); err != nil {
logger.Error(ctx, "unmarshal async task create request failed", "error", err)
renderRespFailure(c, constants.RespCodeInvalidParams, "invalid request parameters", nil)
return
}
// validate task type
if !orm.IsValidAsyncTaskType(request.TaskType) {
logger.Error(ctx, "check task type invalid", "task_type", request.TaskType)
renderRespFailure(c, constants.RespCodeInvalidParams, "invalid task type", nil)
return
}
// validate task parameters based on task type
if !validateTaskParams(request.TaskType, request.Params) {
logger.Error(ctx, "check task parameters invalid", "task_type", request.TaskType, "params", request.Params)
renderRespFailure(c, constants.RespCodeInvalidParams, "invalid task parameters", nil)
return
}
pgClient := database.GetPostgresDBClient()
if pgClient == nil {
logger.Error(ctx, "database connection not found in context")
renderRespFailure(c, constants.RespCodeServerError, "database connection error", nil)
return
}
// create task in database
taskType := orm.AsyncTaskType(request.TaskType)
params := orm.JSONMap(request.Params)
asyncTask, err := database.CreateAsyncTask(ctx, pgClient, taskType, params)
if err != nil {
logger.Error(ctx, "create async task in database failed", "error", err)
renderRespFailure(c, constants.RespCodeServerError, "failed to create task", nil)
return
}
// enqueue task to channel for async publishing to RabbitMQ
msg := task.NewTaskQueueMessageWithPriority(asyncTask.TaskID, task.TaskType(request.TaskType), 5)
// propagate HTTP request trace so the async chain stays on the same traceID
if v, _ := ctx.Value(constants.CtxKeyTraceID).(string); v != "" {
msg.TraceID = v
}
if v, _ := ctx.Value(constants.CtxKeySpanID).(string); v != "" {
msg.SpanID = v
}
task.TaskMsgChan <- msg
logger.Info(ctx, "task enqueued to channel", "task_id", asyncTask.TaskID, "queue", constants.TaskQueueName)
logger.Info(ctx, "async task created success", "task_id", asyncTask.TaskID, "task_type", request.TaskType)
// return success response
payload := genAsyncTaskCreatePayload(asyncTask.TaskID.String())
renderRespSuccess(c, constants.RespCodeSuccess, "task created successfully", payload)
}
func validateTaskParams(taskType string, params map[string]any) bool {
switch taskType {
case string(orm.AsyncTaskTypeTopologyAnalysis):
return validateTopologyAnalysisParams(params)
case string(orm.AsyncTaskTypePerformanceAnalysis):
return validatePerformanceAnalysisParams(params)
case string(orm.AsyncTaskTypeEventAnalysis):
return validateEventAnalysisParams(params)
case string(orm.AsyncTaskTypeBatchImport):
return validateBatchImportParams(params)
case string(orm.AsyncTaskTypeTest):
return validateTestTaskParams(params)
default:
return false
}
}
func validateTopologyAnalysisParams(params map[string]any) bool {
// Check required parameters for topology analysis
if startUUID, ok := params["start_uuid"]; !ok || startUUID == "" {
return false
}
if endUUID, ok := params["end_uuid"]; !ok || endUUID == "" {
return false
}
return true
}
func validatePerformanceAnalysisParams(params map[string]any) bool {
// Check required parameters for performance analysis
if componentIDs, ok := params["component_ids"]; !ok {
return false
} else if ids, isSlice := componentIDs.([]interface{}); !isSlice || len(ids) == 0 {
return false
}
return true
}
func validateEventAnalysisParams(params map[string]any) bool {
// Check required parameters for event analysis
if eventType, ok := params["event_type"]; !ok || eventType == "" {
return false
}
return true
}
func validateBatchImportParams(params map[string]any) bool {
// Check required parameters for batch import
if filePath, ok := params["file_path"]; !ok || filePath == "" {
return false
}
return true
}
func validateTestTaskParams(params map[string]any) bool {
// Test task has optional parameters, all are valid
// sleep_duration defaults to 60 seconds if not provided
return true
}
func genAsyncTaskCreatePayload(taskID string) map[string]any {
payload := map[string]any{
"task_id": taskID,
}
return payload
}