scheduled_test_handler.go 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. package admin
  2. import (
  3. "net/http"
  4. "strconv"
  5. "github.com/Wei-Shaw/sub2api/internal/pkg/response"
  6. "github.com/Wei-Shaw/sub2api/internal/service"
  7. "github.com/gin-gonic/gin"
  8. )
  9. // ScheduledTestHandler handles admin scheduled-test-plan management.
  10. type ScheduledTestHandler struct {
  11. scheduledTestSvc *service.ScheduledTestService
  12. }
  13. // NewScheduledTestHandler creates a new ScheduledTestHandler.
  14. func NewScheduledTestHandler(scheduledTestSvc *service.ScheduledTestService) *ScheduledTestHandler {
  15. return &ScheduledTestHandler{scheduledTestSvc: scheduledTestSvc}
  16. }
  17. type createScheduledTestPlanRequest struct {
  18. AccountID int64 `json:"account_id" binding:"required"`
  19. ModelID string `json:"model_id"`
  20. CronExpression string `json:"cron_expression" binding:"required"`
  21. Enabled *bool `json:"enabled"`
  22. MaxResults int `json:"max_results"`
  23. AutoRecover *bool `json:"auto_recover"`
  24. }
  25. type updateScheduledTestPlanRequest struct {
  26. ModelID string `json:"model_id"`
  27. CronExpression string `json:"cron_expression"`
  28. Enabled *bool `json:"enabled"`
  29. MaxResults int `json:"max_results"`
  30. AutoRecover *bool `json:"auto_recover"`
  31. }
  32. // ListByAccount GET /admin/accounts/:id/scheduled-test-plans
  33. func (h *ScheduledTestHandler) ListByAccount(c *gin.Context) {
  34. accountID, err := strconv.ParseInt(c.Param("id"), 10, 64)
  35. if err != nil {
  36. response.BadRequest(c, "invalid account id")
  37. return
  38. }
  39. plans, err := h.scheduledTestSvc.ListPlansByAccount(c.Request.Context(), accountID)
  40. if err != nil {
  41. response.InternalError(c, err.Error())
  42. return
  43. }
  44. c.JSON(http.StatusOK, plans)
  45. }
  46. // Create POST /admin/scheduled-test-plans
  47. func (h *ScheduledTestHandler) Create(c *gin.Context) {
  48. var req createScheduledTestPlanRequest
  49. if err := c.ShouldBindJSON(&req); err != nil {
  50. response.BadRequest(c, err.Error())
  51. return
  52. }
  53. plan := &service.ScheduledTestPlan{
  54. AccountID: req.AccountID,
  55. ModelID: req.ModelID,
  56. CronExpression: req.CronExpression,
  57. Enabled: true,
  58. MaxResults: req.MaxResults,
  59. }
  60. if req.Enabled != nil {
  61. plan.Enabled = *req.Enabled
  62. }
  63. if req.AutoRecover != nil {
  64. plan.AutoRecover = *req.AutoRecover
  65. }
  66. created, err := h.scheduledTestSvc.CreatePlan(c.Request.Context(), plan)
  67. if err != nil {
  68. response.BadRequest(c, err.Error())
  69. return
  70. }
  71. c.JSON(http.StatusOK, created)
  72. }
  73. // Update PUT /admin/scheduled-test-plans/:id
  74. func (h *ScheduledTestHandler) Update(c *gin.Context) {
  75. planID, err := strconv.ParseInt(c.Param("id"), 10, 64)
  76. if err != nil {
  77. response.BadRequest(c, "invalid plan id")
  78. return
  79. }
  80. existing, err := h.scheduledTestSvc.GetPlan(c.Request.Context(), planID)
  81. if err != nil {
  82. response.NotFound(c, "plan not found")
  83. return
  84. }
  85. var req updateScheduledTestPlanRequest
  86. if err := c.ShouldBindJSON(&req); err != nil {
  87. response.BadRequest(c, err.Error())
  88. return
  89. }
  90. if req.ModelID != "" {
  91. existing.ModelID = req.ModelID
  92. }
  93. if req.CronExpression != "" {
  94. existing.CronExpression = req.CronExpression
  95. }
  96. if req.Enabled != nil {
  97. existing.Enabled = *req.Enabled
  98. }
  99. if req.MaxResults > 0 {
  100. existing.MaxResults = req.MaxResults
  101. }
  102. if req.AutoRecover != nil {
  103. existing.AutoRecover = *req.AutoRecover
  104. }
  105. updated, err := h.scheduledTestSvc.UpdatePlan(c.Request.Context(), existing)
  106. if err != nil {
  107. response.BadRequest(c, err.Error())
  108. return
  109. }
  110. c.JSON(http.StatusOK, updated)
  111. }
  112. // Delete DELETE /admin/scheduled-test-plans/:id
  113. func (h *ScheduledTestHandler) Delete(c *gin.Context) {
  114. planID, err := strconv.ParseInt(c.Param("id"), 10, 64)
  115. if err != nil {
  116. response.BadRequest(c, "invalid plan id")
  117. return
  118. }
  119. if err := h.scheduledTestSvc.DeletePlan(c.Request.Context(), planID); err != nil {
  120. response.InternalError(c, err.Error())
  121. return
  122. }
  123. c.JSON(http.StatusOK, gin.H{"message": "deleted"})
  124. }
  125. // ListResults GET /admin/scheduled-test-plans/:id/results
  126. func (h *ScheduledTestHandler) ListResults(c *gin.Context) {
  127. planID, err := strconv.ParseInt(c.Param("id"), 10, 64)
  128. if err != nil {
  129. response.BadRequest(c, "invalid plan id")
  130. return
  131. }
  132. limit := 50
  133. if l, err := strconv.Atoi(c.Query("limit")); err == nil && l > 0 {
  134. limit = l
  135. }
  136. results, err := h.scheduledTestSvc.ListResults(c.Request.Context(), planID, limit)
  137. if err != nil {
  138. response.InternalError(c, err.Error())
  139. return
  140. }
  141. c.JSON(http.StatusOK, results)
  142. }