152 lines
4.1 KiB
Go
152 lines
4.1 KiB
Go
// Package handler provides HTTP handlers for various endpoints.
|
||
package handler
|
||
|
||
import (
|
||
"strings"
|
||
|
||
"modelRT/constants"
|
||
"modelRT/database"
|
||
"modelRT/logger"
|
||
"modelRT/network"
|
||
"modelRT/orm"
|
||
|
||
"github.com/gin-gonic/gin"
|
||
"github.com/gofrs/uuid"
|
||
)
|
||
|
||
// AsyncTaskResultQueryHandler handles querying of asynchronous task results
|
||
// @Summary 查询异步任务结果
|
||
// @Description 根据任务ID列表查询异步任务的状态和结果
|
||
// @Tags AsyncTask
|
||
// @Accept json
|
||
// @Produce json
|
||
// @Param task_ids query string true "任务ID列表,用逗号分隔"
|
||
// @Success 200 {object} network.SuccessResponse{payload=network.AsyncTaskResultQueryResponse} "查询成功"
|
||
// @Failure 200 {object} network.FailureResponse "请求参数错误"
|
||
// @Router /task/async/results [get]
|
||
func AsyncTaskResultQueryHandler(c *gin.Context) {
|
||
ctx := c.Request.Context()
|
||
|
||
taskIDsParam := c.Query("task_ids")
|
||
if taskIDsParam == "" {
|
||
logger.Error(ctx, "task_ids parameter is required")
|
||
renderRespFailure(c, constants.RespCodeInvalidParams, "task_ids parameter is required", nil)
|
||
return
|
||
}
|
||
|
||
var taskIDs []uuid.UUID
|
||
taskIDStrs := splitCommaSeparated(taskIDsParam)
|
||
for _, taskIDStr := range taskIDStrs {
|
||
taskID, err := uuid.FromString(taskIDStr)
|
||
if err != nil {
|
||
logger.Error(ctx, "invalid task ID format", "task_id", taskIDStr, "error", err)
|
||
renderRespFailure(c, constants.RespCodeInvalidParams, "invalid task ID format", nil)
|
||
return
|
||
}
|
||
taskIDs = append(taskIDs, taskID)
|
||
}
|
||
|
||
if len(taskIDs) == 0 {
|
||
logger.Error(ctx, "no valid task IDs provided")
|
||
renderRespFailure(c, constants.RespCodeInvalidParams, "no valid task IDs provided", 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
|
||
}
|
||
|
||
asyncTasks, err := database.GetAsyncTasksByIDs(ctx, pgClient, taskIDs)
|
||
if err != nil {
|
||
logger.Error(ctx, "failed to query async tasks from database", "error", err)
|
||
renderRespFailure(c, constants.RespCodeServerError, "failed to query tasks", nil)
|
||
return
|
||
}
|
||
|
||
taskResults, err := database.GetAsyncTaskResults(ctx, pgClient, taskIDs)
|
||
if err != nil {
|
||
logger.Error(ctx, "failed to query async task results from database", "error", err)
|
||
renderRespFailure(c, constants.RespCodeServerError, "failed to query task results", nil)
|
||
return
|
||
}
|
||
|
||
taskResultMap := make(map[uuid.UUID]orm.AsyncTaskResult)
|
||
for _, result := range taskResults {
|
||
taskResultMap[result.TaskID] = result
|
||
}
|
||
|
||
var responseTasks []network.AsyncTaskResult
|
||
for _, asyncTask := range asyncTasks {
|
||
taskResult := network.AsyncTaskResult{
|
||
TaskID: asyncTask.TaskID,
|
||
TaskType: string(asyncTask.TaskType),
|
||
Status: string(asyncTask.Status),
|
||
CreatedAt: asyncTask.CreatedAt,
|
||
FinishedAt: asyncTask.FinishedAt,
|
||
Progress: asyncTask.Progress,
|
||
}
|
||
|
||
if result, exists := taskResultMap[asyncTask.TaskID]; exists {
|
||
if result.Result != nil {
|
||
taskResult.Result = map[string]any(result.Result)
|
||
}
|
||
if result.ErrorCode != nil {
|
||
taskResult.ErrorCode = result.ErrorCode
|
||
}
|
||
if result.ErrorMessage != nil {
|
||
taskResult.ErrorMessage = result.ErrorMessage
|
||
}
|
||
if result.ErrorDetail != nil {
|
||
taskResult.ErrorDetail = map[string]any(result.ErrorDetail)
|
||
}
|
||
}
|
||
|
||
responseTasks = append(responseTasks, taskResult)
|
||
}
|
||
|
||
renderRespSuccess(c, constants.RespCodeSuccess, "query completed", network.AsyncTaskResultQueryResponse{
|
||
Total: len(responseTasks),
|
||
Tasks: responseTasks,
|
||
})
|
||
}
|
||
|
||
func splitCommaSeparated(s string) []string {
|
||
var result []string
|
||
var current strings.Builder
|
||
inQuotes := false
|
||
escape := false
|
||
|
||
for _, ch := range s {
|
||
if escape {
|
||
current.WriteRune(ch)
|
||
escape = false
|
||
continue
|
||
}
|
||
|
||
switch ch {
|
||
case '\\':
|
||
escape = true
|
||
case '"':
|
||
inQuotes = !inQuotes
|
||
case ',':
|
||
if !inQuotes {
|
||
result = append(result, strings.TrimSpace(current.String()))
|
||
current.Reset()
|
||
} else {
|
||
current.WriteRune(ch)
|
||
}
|
||
default:
|
||
current.WriteRune(ch)
|
||
}
|
||
}
|
||
|
||
if current.Len() > 0 {
|
||
result = append(result, strings.TrimSpace(current.String()))
|
||
}
|
||
|
||
return result
|
||
}
|