package handler import ( "net/http" "gcy_hpc_server/internal/model" "gcy_hpc_server/internal/server" "gcy_hpc_server/internal/service" "github.com/gin-gonic/gin" "go.uber.org/zap" ) // JobHandler handles HTTP requests for job operations. type JobHandler struct { jobSvc *service.JobService logger *zap.Logger } // NewJobHandler creates a new JobHandler with the given JobService. func NewJobHandler(jobSvc *service.JobService, logger *zap.Logger) *JobHandler { return &JobHandler{jobSvc: jobSvc, logger: logger} } // SubmitJob handles POST /api/v1/jobs/submit. func (h *JobHandler) SubmitJob(c *gin.Context) { var req model.SubmitJobRequest if err := c.ShouldBindJSON(&req); err != nil { h.logger.Warn("bad request", zap.String("method", "SubmitJob"), zap.String("error", "invalid request body")) server.BadRequest(c, "invalid request body") return } if req.Script == "" { h.logger.Warn("bad request", zap.String("method", "SubmitJob"), zap.String("error", "script is required")) server.BadRequest(c, "script is required") return } resp, err := h.jobSvc.SubmitJob(c.Request.Context(), &req) if err != nil { h.logger.Error("handler error", zap.String("method", "SubmitJob"), zap.Int("status", http.StatusBadGateway), zap.Error(err)) server.ErrorWithStatus(c, http.StatusBadGateway, "slurm error: "+err.Error()) return } server.Created(c, resp) } // GetJobs handles GET /api/v1/jobs. func (h *JobHandler) GetJobs(c *gin.Context) { jobs, err := h.jobSvc.GetJobs(c.Request.Context()) if err != nil { h.logger.Error("handler error", zap.String("method", "GetJobs"), zap.Int("status", http.StatusInternalServerError), zap.Error(err)) server.InternalError(c, err.Error()) return } server.OK(c, jobs) } // GetJob handles GET /api/v1/jobs/:id. func (h *JobHandler) GetJob(c *gin.Context) { jobID := c.Param("id") resp, err := h.jobSvc.GetJob(c.Request.Context(), jobID) if err != nil { h.logger.Error("handler error", zap.String("method", "GetJob"), zap.Int("status", http.StatusInternalServerError), zap.Error(err)) server.InternalError(c, err.Error()) return } if resp == nil { h.logger.Warn("bad request", zap.String("method", "GetJob"), zap.String("error", "job not found")) server.NotFound(c, "job not found") return } server.OK(c, resp) } // CancelJob handles DELETE /api/v1/jobs/:id. func (h *JobHandler) CancelJob(c *gin.Context) { jobID := c.Param("id") err := h.jobSvc.CancelJob(c.Request.Context(), jobID) if err != nil { h.logger.Error("handler error", zap.String("method", "CancelJob"), zap.Int("status", http.StatusBadGateway), zap.Error(err)) server.ErrorWithStatus(c, http.StatusBadGateway, err.Error()) return } server.OK(c, gin.H{"message": "job cancelled"}) } // GetJobHistory handles GET /api/v1/jobs/history. func (h *JobHandler) GetJobHistory(c *gin.Context) { var query model.JobHistoryQuery if err := c.ShouldBindQuery(&query); err != nil { h.logger.Warn("bad request", zap.String("method", "GetJobHistory"), zap.String("error", "invalid query params")) server.BadRequest(c, "invalid query params") return } if query.Page < 1 { query.Page = 1 } if query.PageSize < 1 { query.PageSize = 20 } resp, err := h.jobSvc.GetJobHistory(c.Request.Context(), &query) if err != nil { h.logger.Error("handler error", zap.String("method", "GetJobHistory"), zap.Int("status", http.StatusInternalServerError), zap.Error(err)) server.InternalError(c, err.Error()) return } server.OK(c, resp) }