| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168 |
- package handler
- import (
- "fmt"
- "net/http"
- "strconv"
- "time"
- "spider/internal/model"
- "spider/internal/store"
- "spider/internal/task"
- "github.com/gin-gonic/gin"
- )
- // ScheduleHandler handles schedule CRUD endpoints.
- type ScheduleHandler struct {
- store *store.Store
- scheduler *task.Scheduler
- taskMgr *task.Manager
- }
- // SetScheduler sets the scheduler reference (called after scheduler is created).
- func (h *ScheduleHandler) SetScheduler(s *task.Scheduler) {
- h.scheduler = s
- }
- // List handles GET /schedules
- func (h *ScheduleHandler) List(c *gin.Context) {
- var jobs []model.ScheduleJob
- if err := h.store.DB.Order("id ASC").Find(&jobs).Error; err != nil {
- Fail(c, 500, err.Error())
- return
- }
- OK(c, jobs)
- }
- // Create handles POST /schedules
- func (h *ScheduleHandler) Create(c *gin.Context) {
- var req struct {
- Name string `json:"name" binding:"required"`
- PluginName string `json:"plugin_name" binding:"required"`
- CronExpr string `json:"cron_expr" binding:"required"`
- }
- if err := c.ShouldBindJSON(&req); err != nil {
- Fail(c, 400, err.Error())
- return
- }
- job := model.ScheduleJob{
- Name: req.Name,
- PluginName: req.PluginName,
- CronExpr: req.CronExpr,
- Enabled: true,
- }
- if err := h.store.DB.Create(&job).Error; err != nil {
- Fail(c, 500, err.Error())
- return
- }
- if h.scheduler != nil {
- h.scheduler.Reload()
- }
- LogAudit(h.store, c, "create", "schedule", fmt.Sprintf("%d", job.ID), gin.H{"name": job.Name, "plugin": job.PluginName})
- OK(c, job)
- }
- // Update handles PUT /schedules/:id
- func (h *ScheduleHandler) Update(c *gin.Context) {
- id, err := strconv.ParseUint(c.Param("id"), 10, 64)
- if err != nil {
- Fail(c, 400, "invalid id")
- return
- }
- var job model.ScheduleJob
- if err := h.store.DB.First(&job, id).Error; err != nil {
- Fail(c, 404, "定时任务不存在")
- return
- }
- var req struct {
- Name *string `json:"name"`
- CronExpr *string `json:"cron_expr"`
- Enabled *bool `json:"enabled"`
- }
- if err := c.ShouldBindJSON(&req); err != nil {
- Fail(c, 400, err.Error())
- return
- }
- updates := map[string]any{}
- if req.Name != nil {
- updates["name"] = *req.Name
- }
- if req.CronExpr != nil {
- updates["cron_expr"] = *req.CronExpr
- }
- if req.Enabled != nil {
- updates["enabled"] = *req.Enabled
- }
- if len(updates) > 0 {
- if err := h.store.DB.Model(&job).Updates(updates).Error; err != nil {
- Fail(c, 500, err.Error())
- return
- }
- }
- // Re-read
- h.store.DB.First(&job, id)
- if h.scheduler != nil {
- h.scheduler.Reload()
- }
- LogAudit(h.store, c, "update", "schedule", fmt.Sprintf("%d", id), updates)
- OK(c, job)
- }
- // Delete handles DELETE /schedules/:id
- func (h *ScheduleHandler) Delete(c *gin.Context) {
- id, err := strconv.ParseUint(c.Param("id"), 10, 64)
- if err != nil {
- Fail(c, 400, "invalid id")
- return
- }
- if err := h.store.DB.Delete(&model.ScheduleJob{}, id).Error; err != nil {
- Fail(c, 500, err.Error())
- return
- }
- if h.scheduler != nil {
- h.scheduler.Reload()
- }
- LogAudit(h.store, c, "delete", "schedule", fmt.Sprintf("%d", id), nil)
- OK(c, nil)
- }
- // RunNow handles POST /schedules/:id/run — manually triggers a scheduled job immediately
- func (h *ScheduleHandler) RunNow(c *gin.Context) {
- id, err := strconv.ParseUint(c.Param("id"), 10, 64)
- if err != nil {
- Fail(c, 400, "invalid id")
- return
- }
- var job model.ScheduleJob
- if err := h.store.DB.First(&job, id).Error; err != nil {
- Fail(c, 404, "定时任务不存在")
- return
- }
- // Start the task using the task manager via scheduler
- req := task.StartRequest{PluginName: job.PluginName}
- taskLog, err := h.taskMgr.StartTask(req)
- if err != nil {
- Fail(c, 409, err.Error())
- return
- }
- // Update last_run_at
- now := time.Now()
- h.store.DB.Model(&job).Update("last_run_at", now)
- LogAudit(h.store, c, "create", "task", fmt.Sprintf("%d", taskLog.ID), gin.H{"trigger": "manual_schedule", "schedule_id": id})
- c.JSON(http.StatusCreated, Response{Code: 0, Message: "ok", Data: taskLog})
- }
|