182 lines
5.5 KiB
Go
182 lines
5.5 KiB
Go
package server
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"net/http"
|
|
"strconv"
|
|
"time"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
"kra/internal/biz"
|
|
"kra/internal/service"
|
|
)
|
|
|
|
type taskRequest struct {
|
|
ID uint `json:"ID"`
|
|
Name string `json:"name"`
|
|
Description string `json:"description"`
|
|
Spec string `json:"spec"`
|
|
WithSeconds bool `json:"withSeconds"`
|
|
ExecutorType string `json:"executorType"`
|
|
MethodName string `json:"methodName"`
|
|
Params json.RawMessage `json:"params"`
|
|
HTTPURL string `json:"httpUrl"`
|
|
HTTPMethod string `json:"httpMethod"`
|
|
HTTPHeader json.RawMessage `json:"httpHeader"`
|
|
HTTPBody string `json:"httpBody"`
|
|
HTTPAllowPrivate bool `json:"httpAllowPrivate"`
|
|
Enabled bool `json:"enabled"`
|
|
}
|
|
|
|
func taskDomain(v taskRequest) *biz.TimedTask {
|
|
return &biz.TimedTask{ID: v.ID, Name: v.Name, Description: v.Description, Spec: v.Spec, WithSeconds: v.WithSeconds, ExecutorType: v.ExecutorType, MethodName: v.MethodName, Params: v.Params, HTTPURL: v.HTTPURL, HTTPMethod: v.HTTPMethod, HTTPHeader: v.HTTPHeader, HTTPBody: v.HTTPBody, HTTPAllowPrivate: v.HTTPAllowPrivate, Enabled: v.Enabled}
|
|
}
|
|
func registerTaskRoutes(group *gin.RouterGroup, svc *service.TaskService, scheduler *TaskScheduler) {
|
|
router := group.Group("/timedTask")
|
|
router.POST("/createTimedTask", func(c *gin.Context) {
|
|
var req taskRequest
|
|
if c.ShouldBindJSON(&req) != nil {
|
|
fail(c, "参数错误")
|
|
return
|
|
}
|
|
task := taskDomain(req)
|
|
if err := svc.Create(c.Request.Context(), task); err != nil {
|
|
fail(c, "创建失败:"+err.Error())
|
|
return
|
|
}
|
|
if err := scheduler.Schedule(task); err != nil {
|
|
fail(c, "调度失败:"+err.Error())
|
|
return
|
|
}
|
|
ok(c)
|
|
})
|
|
router.PUT("/updateTimedTask", func(c *gin.Context) {
|
|
var req taskRequest
|
|
if c.ShouldBindJSON(&req) != nil {
|
|
fail(c, "参数错误")
|
|
return
|
|
}
|
|
task := taskDomain(req)
|
|
if err := svc.Update(c.Request.Context(), task); err != nil {
|
|
fail(c, "更新失败:"+err.Error())
|
|
return
|
|
}
|
|
if err := scheduler.Schedule(task); err != nil {
|
|
fail(c, "调度失败:"+err.Error())
|
|
return
|
|
}
|
|
ok(c)
|
|
})
|
|
router.DELETE("/deleteTimedTask", func(c *gin.Context) {
|
|
id, _ := strconv.ParseUint(c.Query("ID"), 10, 64)
|
|
scheduler.Remove(uint(id))
|
|
if err := svc.Delete(c.Request.Context(), uint(id)); err != nil {
|
|
fail(c, "删除失败")
|
|
return
|
|
}
|
|
ok(c)
|
|
})
|
|
router.POST("/toggleTimedTask", func(c *gin.Context) {
|
|
var req struct {
|
|
ID uint `json:"ID"`
|
|
Enabled bool `json:"enabled"`
|
|
}
|
|
if c.ShouldBindJSON(&req) != nil {
|
|
fail(c, "参数错误")
|
|
return
|
|
}
|
|
if err := svc.Toggle(c.Request.Context(), req.ID, req.Enabled); err != nil {
|
|
fail(c, "设置失败")
|
|
return
|
|
}
|
|
task, err := svc.Task(c.Request.Context(), req.ID)
|
|
if err != nil {
|
|
fail(c, "任务不存在")
|
|
return
|
|
}
|
|
if err = scheduler.Schedule(task); err != nil {
|
|
fail(c, "调度失败")
|
|
return
|
|
}
|
|
ok(c)
|
|
})
|
|
router.POST("/triggerTimedTask", func(c *gin.Context) {
|
|
var req struct {
|
|
ID uint `json:"ID"`
|
|
}
|
|
if c.ShouldBindJSON(&req) != nil {
|
|
fail(c, "参数错误")
|
|
return
|
|
}
|
|
task, err := svc.Task(c.Request.Context(), req.ID)
|
|
if err != nil {
|
|
fail(c, "任务不存在")
|
|
return
|
|
}
|
|
scheduler.Trigger(task)
|
|
ok(c)
|
|
})
|
|
router.GET("/getTimedTaskList", func(c *gin.Context) {
|
|
page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
|
|
size, _ := strconv.Atoi(c.DefaultQuery("pageSize", "10"))
|
|
var enabled *bool
|
|
if raw := c.Query("enabled"); raw != "" {
|
|
value, _ := strconv.ParseBool(raw)
|
|
enabled = &value
|
|
}
|
|
items, total, err := svc.Tasks(c.Request.Context(), page, size, &biz.TimedTask{Name: c.Query("name"), ExecutorType: c.Query("executorType"), EnabledFilter: enabled}, scheduler.NextRuns())
|
|
if err != nil {
|
|
fail(c, "获取失败")
|
|
return
|
|
}
|
|
writeResult(c, codeSuccess, pageResult{List: items, Total: total, Page: page, PageSize: size}, "获取成功")
|
|
})
|
|
router.GET("/getTimedTaskLogList", func(c *gin.Context) {
|
|
page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
|
|
size, _ := strconv.Atoi(c.DefaultQuery("pageSize", "10"))
|
|
taskID, _ := strconv.ParseUint(c.Query("taskId"), 10, 64)
|
|
items, total, err := svc.Logs(c.Request.Context(), page, size, uint(taskID), c.Query("status"))
|
|
if err != nil {
|
|
fail(c, "获取失败")
|
|
return
|
|
}
|
|
writeResult(c, codeSuccess, pageResult{List: items, Total: total, Page: page, PageSize: size}, "获取成功")
|
|
})
|
|
router.GET("/getRegisteredMethods", func(c *gin.Context) {
|
|
writeResult(c, codeSuccess, gin.H{"methods": svc.RegisteredMethods()}, "获取成功")
|
|
})
|
|
router.GET("/alertStream", func(c *gin.Context) {
|
|
c.Header("Content-Type", "text/event-stream")
|
|
c.Header("Cache-Control", "no-cache")
|
|
c.Header("Connection", "keep-alive")
|
|
c.Header("X-Accel-Buffering", "no")
|
|
flusher, okFlush := c.Writer.(http.Flusher)
|
|
if !okFlush {
|
|
fail(c, "SSE 不受支持")
|
|
return
|
|
}
|
|
events := scheduler.Subscribe()
|
|
defer scheduler.Unsubscribe(events)
|
|
ticker := time.NewTicker(20 * time.Second)
|
|
defer ticker.Stop()
|
|
_, _ = fmt.Fprint(c.Writer, "event: connected\ndata: {}\n\n")
|
|
flusher.Flush()
|
|
for {
|
|
select {
|
|
case event, open := <-events:
|
|
if !open {
|
|
return
|
|
}
|
|
_, _ = fmt.Fprintf(c.Writer, "event: alert\ndata: %s\n\n", event)
|
|
flusher.Flush()
|
|
case <-ticker.C:
|
|
_, _ = fmt.Fprint(c.Writer, ": keepalive\n\n")
|
|
flusher.Flush()
|
|
case <-c.Request.Context().Done():
|
|
return
|
|
}
|
|
}
|
|
})
|
|
}
|