feat(job-array-one-based-index): control by identity validates first and dispatches once (task 7.4)
ControlJobByID parses every selection with ParseIdentitySelection before any store access (first rejection: 400, nothing dispatched), collects the jobs to act on de-duplicated by unique_job_id plus one not-found result per missing number per selection (carrying the would-be element ID), validates each job once after the loop and dispatches each accepted job once. foundJob gains an explicit-index flag so <array-id>[0] matches only element 0 and never falls back to the whole array or an ordinary job. Fixes bug-1899 (earlier selections were re-dispatched for every later one). Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
c3962e8f61
commit
4020740208
4 changed files with 475 additions and 241 deletions
|
|
@ -2,6 +2,7 @@ package controllers
|
|||
|
||||
import (
|
||||
"errors"
|
||||
"apiserver/backend"
|
||||
"apiserver/models"
|
||||
"apiserver/store"
|
||||
"apiserver/utils"
|
||||
|
|
@ -179,13 +180,17 @@ func TestValidateJobControl_RejectsNonKillableStatus(t *testing.T) {
|
|||
func TestFoundJob_MatchesRealArrayIdxType(t *testing.T) {
|
||||
resetJobSubmitState()
|
||||
|
||||
// an array element: its unique_job_id carries the array marking
|
||||
const key = uint64(2)<<40 | uint64(1)<<20
|
||||
elem := backend.MakeElementID(key, 1)
|
||||
jobInfo := models.JobInfo{
|
||||
JobID: 1788186846,
|
||||
ArrayIdx: 1,
|
||||
Unique_JobID: int64(elem),
|
||||
JobID: int64(key),
|
||||
ArrayIdx: 1,
|
||||
}
|
||||
orderMap := store.StructToOrderMap(jobInfo)
|
||||
|
||||
found, err := foundJob(1788186846, 1, []utils.OrderMap{orderMap})
|
||||
found, err := foundJob(int64(key), 1, true, []utils.OrderMap{orderMap})
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
|
|
@ -194,6 +199,49 @@ func TestFoundJob_MatchesRealArrayIdxType(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
// TestFoundJob_ExplicitIndex (5.4, 5.6, 8.2): an explicit element number
|
||||
// matches only array elements with that number -- never an ordinary job with
|
||||
// array_idx 0 or the whole array -- while no element part matches every row
|
||||
// with that job_id.
|
||||
func TestFoundJob_ExplicitIndex(t *testing.T) {
|
||||
const key = uint64(2)<<40 | uint64(1)<<20
|
||||
row := func(uid uint64, idx int) utils.OrderMap {
|
||||
return store.StructToOrderMap(models.JobInfo{Unique_JobID: int64(uid), JobID: int64(key), ArrayIdx: idx})
|
||||
}
|
||||
ordinary := row(key, 0) // an ordinary job sharing the number
|
||||
e1 := row(backend.MakeElementID(key, 1), 1)
|
||||
e2 := row(backend.MakeElementID(key, 2), 2)
|
||||
withZero := []utils.OrderMap{ordinary, e1, e2, row(backend.MakeElementID(key, 0), 0)}
|
||||
noZero := []utils.OrderMap{ordinary, e1, e2}
|
||||
|
||||
uids := func(rows []utils.OrderMap) []int64 {
|
||||
out := []int64{}
|
||||
for _, r := range rows {
|
||||
out = append(out, r.Data["unique_job_id"].(int64))
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
if got, err := foundJob(int64(key), 0, true, noZero); err == nil {
|
||||
t.Errorf("[0] without element 0 matched %v, want not found", uids(got))
|
||||
}
|
||||
got, err := foundJob(int64(key), 0, true, withZero)
|
||||
if err != nil || len(got) != 1 || uint64(got[0].Data["unique_job_id"].(int64)) != backend.MakeElementID(key, 0) {
|
||||
t.Errorf("[0] with a pre-upgrade element 0 = %v, %v; want that element alone", uids(got), err)
|
||||
}
|
||||
got, err = foundJob(int64(key), 2, true, noZero)
|
||||
if err != nil || len(got) != 1 || uint64(got[0].Data["unique_job_id"].(int64)) != backend.MakeElementID(key, 2) {
|
||||
t.Errorf("[2] = %v, %v; want element 2 alone", uids(got), err)
|
||||
}
|
||||
if got, err := foundJob(int64(key), 3, true, noZero); err == nil {
|
||||
t.Errorf("[3] matched %v, want not found", uids(got))
|
||||
}
|
||||
got, err = foundJob(int64(key), 0, false, noZero)
|
||||
if err != nil || len(got) != 3 {
|
||||
t.Errorf("bare = %v, %v; want every row with that job_id", uids(got), err)
|
||||
}
|
||||
}
|
||||
|
||||
// TestPreCheckJobRequest_RejectsMalformedResreq (bug-1744): a resource request
|
||||
// the syntax check rejects must fail the submission instead of being accepted
|
||||
// and later silently dropped by the scheduler.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue