|
- // Copyright 2025 The HuaTuo Authors
- //
- // Licensed under the Apache License, Version 2.0 (the "License");
- // you may not use this file except in compliance with the License.
- // You may obtain a copy of the License at
- //
- // http://www.apache.org/licenses/LICENSE-2.0
- //
- // Unless required by applicable law or agreed to in writing, software
- // distributed under the License is distributed on an "AS IS" BASIS,
- // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- // See the License for the specific language governing permissions and
- // limitations under the License.
-
- package services
-
- import (
- "errors"
- "net/http"
- "time"
-
- "huatuo-bamai/internal/conf"
- "huatuo-bamai/pkg/tracing"
-
- "github.com/gin-gonic/gin"
- "github.com/go-playground/validator/v10"
- )
-
- // NewTaskReq represents the structure of the request body for creating a new task.
- type NewTaskReq struct {
- TracerName string `json:"tracer_name" binding:"required"` // Name of the tracer, required field
- Timeout int `json:"timeout" binding:"required,number,lt=3600"` // Timeout in seconds, must be less than 3600s(1 hour)
- DataType string `json:"data_type" binding:"required"` // Type of data to be handled, required field
- TracerArgs []string `json:"trace_args" binding:"omitempty"` // Additional arguments for the tracer, optional field
- }
-
- // StopTaskReq represents the structure of the request body for stopping a task.
- type StopTaskReq struct {
- TaskID string `json:"id" binding:"required"` // Identifier of the task to stop, required field
- }
-
- func handleBindError(ctx *gin.Context, err error) {
- var validationError *validator.ValidationErrors
-
- if errors.As(err, &validationError) {
- ctx.JSON(400, gin.H{"body invalid": (*validationError)[0].Namespace()})
- return
- }
-
- ctx.JSON(400, gin.H{"error": err.Error()})
- }
-
- // NewTask creates a new task based on the provided request.
- func NewTask(ctx *gin.Context) {
- var req NewTaskReq
- if err := ctx.ShouldBindJSON(&req); err != nil {
- handleBindError(ctx, err)
- return
- }
-
- if tracing.RunningTaskCount() > conf.Get().TaskConfig.MaxRunningTask {
- ctx.JSON(http.StatusBadRequest, gin.H{"error": "too many running tasks"})
- return
- }
-
- storageDefault := tracing.TaskStorageDB
- if req.DataType == "json" {
- storageDefault = tracing.TaskStorageStdout
- }
-
- id := tracing.NewTask(req.TracerName, time.Duration(req.Timeout)*time.Second, storageDefault, req.TracerArgs)
-
- ctx.JSON(200, gin.H{"task_id": id})
- }
-
- // TaskResult retrieves the result of a task.
- func TaskResult(ctx *gin.Context) {
- id := ctx.Query("id")
- if id == "" {
- ctx.JSON(http.StatusBadRequest, gin.H{"error": "missing task id"})
- return
- }
-
- result := tracing.Result(id)
-
- response := gin.H{"status": result.TaskStatus}
- httpStatus := http.StatusOK
-
- switch result.TaskStatus {
- case tracing.StatusCompleted:
- response["data"] = string(result.TaskData)
- case tracing.StatusNotExist, tracing.StatusFailed:
- response["error"] = result.TaskErr.Error()
- }
- ctx.JSON(httpStatus, response)
- }
-
- // TaskStop stops a running task.
- func TaskStop(ctx *gin.Context) {
- var req StopTaskReq
- if err := ctx.ShouldBindJSON(&req); err != nil {
- handleBindError(ctx, err)
- return
- }
- if err := tracing.StopTask(req.TaskID); err != nil {
- if errors.Is(err, tracing.ErrTaskNotFound) {
- ctx.JSON(http.StatusBadRequest, gin.H{"error": "task not found"})
- return
- }
- ctx.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
- return
- }
- ctx.JSON(http.StatusOK, gin.H{"status": "ok"})
- }
|