171 lines
4.7 KiB
Go
171 lines
4.7 KiB
Go
package handler
|
|
|
|
import (
|
|
"fmt"
|
|
"net/http"
|
|
"strconv"
|
|
"time"
|
|
|
|
"kra/internal/server/httpx"
|
|
"kra/internal/service"
|
|
"kra/internal/service/dto"
|
|
"kra/internal/worker"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
)
|
|
|
|
type Task struct {
|
|
service *service.TaskService
|
|
scheduler *worker.TaskScheduler
|
|
}
|
|
|
|
func NewTask(service *service.TaskService, scheduler *worker.TaskScheduler) *Task {
|
|
return &Task{service: service, scheduler: scheduler}
|
|
}
|
|
|
|
func (h *Task) Create(c *gin.Context) {
|
|
var req dto.TaskRequest
|
|
if c.ShouldBindJSON(&req) != nil {
|
|
httpx.Fail(c, "参数错误")
|
|
return
|
|
}
|
|
id, err := h.service.CreateRequest(c.Request.Context(), &req)
|
|
if err != nil {
|
|
httpx.Fail(c, "创建失败:"+err.Error())
|
|
return
|
|
}
|
|
if err = h.scheduler.ScheduleID(c.Request.Context(), id); err != nil {
|
|
httpx.Fail(c, "调度失败:"+err.Error())
|
|
return
|
|
}
|
|
httpx.Write(c, httpx.CodeSuccess, gin.H{}, "创建成功")
|
|
}
|
|
|
|
func (h *Task) Update(c *gin.Context) {
|
|
var req dto.TaskRequest
|
|
if c.ShouldBindJSON(&req) != nil {
|
|
httpx.Fail(c, "参数错误")
|
|
return
|
|
}
|
|
if err := h.service.UpdateRequest(c.Request.Context(), &req); err != nil {
|
|
httpx.Fail(c, "更新失败:"+err.Error())
|
|
return
|
|
}
|
|
if err := h.scheduler.ScheduleID(c.Request.Context(), req.ID); err != nil {
|
|
httpx.Fail(c, "调度失败:"+err.Error())
|
|
return
|
|
}
|
|
httpx.Write(c, httpx.CodeSuccess, gin.H{}, "更新成功")
|
|
}
|
|
|
|
func (h *Task) Delete(c *gin.Context) {
|
|
var req dto.DeleteTaskRequest
|
|
if c.ShouldBindJSON(&req) != nil || req.ID == 0 {
|
|
httpx.Fail(c, "参数错误")
|
|
return
|
|
}
|
|
h.scheduler.Remove(req.ID)
|
|
if err := h.service.Delete(c.Request.Context(), req.ID); err != nil {
|
|
httpx.Fail(c, "删除失败")
|
|
return
|
|
}
|
|
httpx.Write(c, httpx.CodeSuccess, gin.H{}, "删除成功")
|
|
}
|
|
|
|
func (h *Task) Toggle(c *gin.Context) {
|
|
var req dto.ToggleTaskRequest
|
|
if c.ShouldBindJSON(&req) != nil {
|
|
httpx.Fail(c, "参数错误")
|
|
return
|
|
}
|
|
if err := h.service.Toggle(c.Request.Context(), req.ID, req.Enabled); err != nil {
|
|
httpx.Fail(c, "操作失败: "+err.Error())
|
|
return
|
|
}
|
|
if err := h.scheduler.ScheduleID(c.Request.Context(), req.ID); err != nil {
|
|
httpx.Fail(c, "操作失败: "+err.Error())
|
|
return
|
|
}
|
|
httpx.Write(c, httpx.CodeSuccess, gin.H{}, "操作成功")
|
|
}
|
|
|
|
func (h *Task) Trigger(c *gin.Context) {
|
|
var req dto.DeleteTaskRequest
|
|
if c.ShouldBindJSON(&req) != nil {
|
|
httpx.Fail(c, "参数错误")
|
|
return
|
|
}
|
|
if err := h.scheduler.TriggerID(c.Request.Context(), req.ID); err != nil {
|
|
httpx.Fail(c, "触发失败: "+err.Error())
|
|
return
|
|
}
|
|
httpx.Write(c, httpx.CodeSuccess, gin.H{}, "已触发, 执行结果见执行日志")
|
|
}
|
|
|
|
func (h *Task) List(c *gin.Context) {
|
|
page, _ := strconv.Atoi(c.Query("page"))
|
|
size, _ := strconv.Atoi(c.Query("pageSize"))
|
|
var enabled *bool
|
|
if raw := c.Query("enabled"); raw != "" {
|
|
value, _ := strconv.ParseBool(raw)
|
|
enabled = &value
|
|
}
|
|
items, total, err := h.service.ListRequest(c.Request.Context(), page, size, c.Query("name"), c.Query("executorType"), enabled, h.scheduler.NextRuns())
|
|
if err != nil {
|
|
httpx.Fail(c, "获取失败")
|
|
return
|
|
}
|
|
httpx.Write(c, httpx.CodeSuccess, httpx.PageResult{List: items, Total: total, Page: page, PageSize: size}, "获取成功")
|
|
}
|
|
|
|
func (h *Task) Logs(c *gin.Context) {
|
|
page, _ := strconv.Atoi(c.Query("page"))
|
|
size, _ := strconv.Atoi(c.Query("pageSize"))
|
|
taskID, _ := strconv.ParseUint(c.Query("taskId"), 10, 64)
|
|
items, total, err := h.service.Logs(c.Request.Context(), page, size, uint(taskID), c.Query("status"))
|
|
if err != nil {
|
|
httpx.Fail(c, "获取失败")
|
|
return
|
|
}
|
|
httpx.Write(c, httpx.CodeSuccess, httpx.PageResult{List: items, Total: total, Page: page, PageSize: size}, "获取成功")
|
|
}
|
|
|
|
func (h *Task) Methods(c *gin.Context) {
|
|
httpx.Write(c, httpx.CodeSuccess, gin.H{"methods": h.service.RegisteredMethods()}, "获取成功")
|
|
}
|
|
|
|
func (h *Task) AlertStream(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, ok := c.Writer.(http.Flusher)
|
|
if !ok {
|
|
httpx.Fail(c, "SSE 不受支持")
|
|
return
|
|
}
|
|
// Remove the normal server deadline for long-lived SSE connections.
|
|
_ = http.NewResponseController(c.Writer).SetWriteDeadline(time.Time{})
|
|
events := h.scheduler.Subscribe()
|
|
defer h.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
|
|
}
|
|
}
|
|
}
|