feat(apiserver): expose PEND reason end-to-end (scheduler → API)
The pending_reason field was declared on models.JobInfo but never populated:
scheduler computed PEND reasons and the controller stored them on
job->pend_reasons, yet the data stopped there. Two gaps closed:
1. controller/apiserver.c: apiserver_job_hook_fun now handles
HOOK_DETAIL_SETPREASON by pushing the updated job to API servers (reusing
apiserver_job_update_fun). Without this, a job whose PEND reasons change
never reached the API server — only JOB_NEW/UPDATE/START/EXIT events did,
and setpreason fired none of those.
2. backend/convert.go + convert_pure.go: cJobToModel / rawJobToModel now
extract xce_job_t.pend_reasons (main_reason + host/res reasons) and
marshal them into models.JobInfo.PendingReason as JSONB. models/jobs.go:
pending_reason added to JOB_DEFAULT_COLUMN so default job queries return
it (it was only in JSONBJFields, never selected).
Verified live on t1/t2/t3: a job with resreq "type == nosuchhost" stays
PEND and returns
"pending_reason":{"main_reason":0,"host_reasons":[{"host":"t1","reason":3},
{"host":"t2","reason":3},{"host":"t3","reason":3}]}
(main_reason=3 PREASON_MATCH_FAIL per host) via both /jobs list, /jobs/:id
and the SSE stream. 4 new unit tests (rawJobToModel pendReason marshal +
name mapping), all apiserver backend tests pass.
Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
7b7294dd1e
commit
ac6131dbd7
6 changed files with 225 additions and 0 deletions
|
|
@ -9,6 +9,10 @@ package backend
|
|||
|
||||
// Helper to index into xce_host_alloc_t** (CGO cannot dereference C pointer-to-pointer arrays).
|
||||
static xce_host_alloc_t *job_alloc_host(xce_job_alloc_t *a, int i) { return a->allocs[i]; }
|
||||
|
||||
// Helpers to index into the reason pointer arrays of xce_job_preason_t.
|
||||
static xce_host_reason_t *job_host_reason(xce_job_preason_t *p, int i) { return p->host_based_reasons[i]; }
|
||||
static xce_res_reason_t *job_res_reason(xce_job_preason_t *p, int i) { return p->res_based_reasons[i]; }
|
||||
*/
|
||||
import "C"
|
||||
|
||||
|
|
@ -117,6 +121,30 @@ func cJobToModel(job *C.xce_job_t) *models.JobInfo {
|
|||
}
|
||||
}
|
||||
}
|
||||
// PEND reason: the scheduler pushes these via setpreason; the controller
|
||||
// stores them on job->pend_reasons. Maps to models.JobInfo.PendingReason.
|
||||
if job.pend_reasons != nil {
|
||||
pr := job.pend_reasons
|
||||
r.pendReason = &rawPendReason{
|
||||
MainReason: int(pr.main_reason),
|
||||
MainReasonName: pendReasonName(int(pr.main_reason)),
|
||||
}
|
||||
for i := 0; i < int(pr.nhost_reasons); i++ {
|
||||
hr := C.job_host_reason(pr, C.int(i))
|
||||
if hr != nil && hr.host != nil {
|
||||
r.pendReason.HostReasons = append(r.pendReason.HostReasons,
|
||||
rawHostReason{Host: goString(hr.host), Reason: int(hr.reason)})
|
||||
}
|
||||
}
|
||||
for i := 0; i < int(pr.nres_reasons); i++ {
|
||||
rr := C.job_res_reason(pr, C.int(i))
|
||||
if rr != nil && rr.resource != nil {
|
||||
r.pendReason.ResReasons = append(r.pendReason.ResReasons,
|
||||
rawResReason{Resource: goString(rr.resource),
|
||||
Host: goString(rr.host), Reason: int(rr.reason)})
|
||||
}
|
||||
}
|
||||
}
|
||||
return rawJobToModel(r)
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue