feat!(backend/jobs): don't require agent_id on waitjob
ci-agent / build (push) Failing after 5m30s

This commit is contained in:
2026-04-05 04:57:43 +03:00
parent b1e6775f1b
commit 71a8fa154b
6 changed files with 37 additions and 77 deletions
-20
View File
@@ -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": {
-20
View File
@@ -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": {
-13
View File
@@ -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:
+33 -20
View File
@@ -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,
})
}
+2 -2
View File
@@ -1,8 +1,8 @@
package models
type Job struct {
ID int64
ID int64
AgentID string
JobForInsert
JobForUpdate
}
@@ -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