diff --git a/backend/docs/docs.go b/backend/docs/docs.go index a709695..4264e18 100644 --- a/backend/docs/docs.go +++ b/backend/docs/docs.go @@ -1106,15 +1106,6 @@ const docTemplate = `{ "name": "id", "in": "path", "required": true - }, - { - "description": "Agent reference", - "name": "body", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/internal_handlers.WaitJobIn" - } } ], "responses": { @@ -2923,17 +2914,6 @@ const docTemplate = `{ "type": "string" } } - }, - "internal_handlers.WaitJobIn": { - "type": "object", - "required": [ - "agent_id" - ], - "properties": { - "agent_id": { - "type": "string" - } - } } }, "securityDefinitions": { diff --git a/backend/docs/swagger.json b/backend/docs/swagger.json index f110bd1..d77e71f 100644 --- a/backend/docs/swagger.json +++ b/backend/docs/swagger.json @@ -1095,15 +1095,6 @@ "name": "id", "in": "path", "required": true - }, - { - "description": "Agent reference", - "name": "body", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/internal_handlers.WaitJobIn" - } } ], "responses": { @@ -2912,17 +2903,6 @@ "type": "string" } } - }, - "internal_handlers.WaitJobIn": { - "type": "object", - "required": [ - "agent_id" - ], - "properties": { - "agent_id": { - "type": "string" - } - } } }, "securityDefinitions": { diff --git a/backend/docs/swagger.yaml b/backend/docs/swagger.yaml index 3b8952b..1d43988 100644 --- a/backend/docs/swagger.yaml +++ b/backend/docs/swagger.yaml @@ -513,13 +513,6 @@ definitions: required: - token type: object - internal_handlers.WaitJobIn: - properties: - agent_id: - type: string - required: - - agent_id - type: object info: contact: {} paths: @@ -1165,12 +1158,6 @@ paths: name: id required: true type: integer - - description: Agent reference - in: body - name: body - required: true - schema: - $ref: '#/definitions/internal_handlers.WaitJobIn' produces: - application/json responses: diff --git a/backend/internal/handlers/jobs.go b/backend/internal/handlers/jobs.go index d710864..ee72005 100644 --- a/backend/internal/handlers/jobs.go +++ b/backend/internal/handlers/jobs.go @@ -51,11 +51,6 @@ type JobResult struct { Status int32 `json:"status"` } -// WaitJobIn is the request body for waiting on a job. -type WaitJobIn struct { - AgentID string `json:"agent_id" binding:"required"` -} - // AddJob submits a job to an agent and returns a wait_url for the result. // @Summary Submit a job to an agent // @Description Sends a command to the specified agent and returns a URL to wait for the result @@ -118,14 +113,14 @@ func (h *JobsHandlers) runCommand( } // WaitJob waits for a submitted job to complete (long-poll). -// If the job is already done, returns immediately. +// First checks the database; if already finished, returns immediately. +// Otherwise waits on the agent for the result. // @Summary Wait for job result // @Description Long-polls for a job result. Returns immediately if the job is already finished. // @Tags jobs // @Accept json // @Produce json // @Param id path int true "Job ID" -// @Param body body WaitJobIn true "Agent reference" // @Success 200 {object} JobResult // @Failure 400 {object} map[string]string // @Failure 404 {object} map[string]string @@ -137,32 +132,50 @@ func (h *JobsHandlers) WaitJob(c *gin.Context) { return } - var in WaitJobIn - if err := c.Bind(&in); err != nil { - c.JSON(http.StatusBadRequest, gin.H{"error": "invalid request body"}) + // Check database first + job, err := h.jobRepo.GetJobByID(c.Request.Context(), jid) + if err != nil { + if errors.Is(err, repository.ErrNotFound) { + c.JSON(http.StatusNotFound, gin.H{"error": "job not found"}) + return + } + c.Error(err) return } - agent, ok := h.tracker.GetAgent(in.AgentID) + // If job is already completed (has output or non-zero status), return immediately + if job.Status != 0 || job.Stdout != "" || job.Stderr != "" { + c.JSON(http.StatusOK, JobResult{ + ID: job.ID, + Command: job.Command, + Stdin: job.Stdin, + Stdout: job.Stdout, + Stderr: job.Stderr, + Status: job.Status, + }) + return + } + + // Job is still pending — wait on the agent + agent, ok := h.tracker.GetAgent(job.AgentID) if !ok { - c.Status(http.StatusNotFound) - c.Error(fmt.Errorf("agent not found")) + c.JSON(http.StatusNotFound, gin.H{"error": "agent not found"}) return } - job, err := agent.WaitJob(jid) + ajob, err := agent.WaitJob(jid) if err != nil { c.Error(err) return } c.JSON(http.StatusOK, JobResult{ - ID: job.ID, - Command: job.Command, - Stdin: job.Stdin, - Stdout: job.Stdout, - Stderr: job.Stderr, - Status: job.Status, + ID: ajob.ID, + Command: ajob.Command, + Stdin: ajob.Stdin, + Stdout: ajob.Stdout, + Stderr: ajob.Stderr, + Status: ajob.Status, }) } diff --git a/backend/internal/models/job.go b/backend/internal/models/job.go index b8ab63a..eaa6259 100644 --- a/backend/internal/models/job.go +++ b/backend/internal/models/job.go @@ -1,8 +1,8 @@ package models type Job struct { - ID int64 - + ID int64 + AgentID string JobForInsert JobForUpdate } diff --git a/backend/internal/repository/job_repository.go b/backend/internal/repository/job_repository.go index eeb3946..9a3978f 100644 --- a/backend/internal/repository/job_repository.go +++ b/backend/internal/repository/job_repository.go @@ -87,9 +87,9 @@ func (r *JobRepository) GetJobByID(ctx context.Context, jid int64) (models.Job, var stdinVal *string err := r.DB.QueryRowContext(ctx, - `SELECT id, command, stdin, stdout, stderr, status FROM jobs WHERE id = ?`, + `SELECT id, agent_id, command, stdin, stdout, stderr, status FROM jobs WHERE id = ?`, jid, - ).Scan(&job.ID, &commandJSON, &stdinVal, &job.Stdout, &job.Stderr, &job.Status) + ).Scan(&job.ID, &job.AgentID, &commandJSON, &stdinVal, &job.Stdout, &job.Stderr, &job.Status) if err != nil { if err == sql.ErrNoRows { return models.Job{}, ErrNotFound