feat(scheduler-sim-eager-reconciliation): task 1.1 state-independent dispatch capture
Widens sim_reconcile_unaccounted_jobs()'s trigger gate in sim_loop.c: removes !JOB_IS_RUN(job->state) so a job's recorded DISPATCH decision is captured as soon as the replay reaches the round it occurred in, regardless of the job's current state -- closing bug-1611/bug-1613's residual (a job whose RUN confirmation lands in a later round than its dispatch decision, the realistic case under any real dispatch-to-confirmation latency, was never reconciled). sched_account_jobs()'s own unmodified JOB_IS_RUN charging gate continues to defer actual resource-in-use accounting until the job genuinely transitions to RUN -- no other line in the match/capture/report path changes. Replaces test_reconcile_skips_non_run_state_job (which asserted the bug as correct behavior) with test_reconcile_captures_non_run_state_job_when_dispatch_recorded, proving the opposite for a PEND-state job. Adds the xce-test-rc-file-style spec docs (requirements/design/research/tasks) for this feature. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AgYRU3zDTqNGV5Jk8aiKLg
This commit is contained in:
parent
3891bd909a
commit
e2bb98c87e
6 changed files with 419 additions and 35 deletions
|
|
@ -498,36 +498,58 @@ static void test_reconcile_ignores_non_dispatch_entry_with_matching_jobid(
|
|||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
/* Test 5: the trigger only fires for a RUN-state job -- a PEND-state job */
|
||||
/* with no accounts must never be touched here (the live picker re-derives */
|
||||
/* PEND decisions fresh every round, per design.md's Revalidation */
|
||||
/* Triggers section). */
|
||||
/* Test 5 (scheduler-sim-eager-reconciliation task 1.1, replaces the old */
|
||||
/* test_reconcile_skips_non_run_state_job): the trigger is now */
|
||||
/* state-independent -- a job whose recorded DISPATCH decision is found */
|
||||
/* this round gets its allocation captured regardless of whether it has */
|
||||
/* reached RUN state yet. This is the inverse of the old (buggy) expected */
|
||||
/* behavior: previously a PEND job with a matching recorded DISPATCH entry */
|
||||
/* stayed uncaptured; it must now be captured just like an already-RUN */
|
||||
/* job (Requirement 1.1, 3.1). The dominant real-world case (dispatch and */
|
||||
/* its RUN-state confirmation recorded many rounds apart) depends on this. */
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
static void test_reconcile_skips_non_run_state_job(void)
|
||||
static void
|
||||
test_reconcile_captures_non_run_state_job_when_dispatch_recorded(void)
|
||||
{
|
||||
xce_sched_sim_driver_t sim;
|
||||
xce_sched_job_t* job;
|
||||
xce_job_alloc_t* jalloc;
|
||||
replay_session_t* decoded;
|
||||
|
||||
fixture_init(&sim);
|
||||
|
||||
/* PEND-state, no known allocation yet -- the realistic case: this
|
||||
* job's recorded DISPATCH decision has been found in this round's
|
||||
* replay stream, but its RUN-state confirmation has not been replayed
|
||||
* yet (may land many rounds later). */
|
||||
job = add_job(&(sim.core), 7005ULL, JOB_STAT_PEND, NULL);
|
||||
TEST_ASSERT_NULL(job->accounts);
|
||||
TEST_ASSERT_NULL(job->allocs);
|
||||
|
||||
/* A matching recorded DISPATCH entry is present -- but must not be
|
||||
* consulted at all, since the trigger's RUN-state gate must reject this
|
||||
* job before any lookup happens. */
|
||||
decoded = make_decoded_session(1000ULL, make_dispatch_entry(7005ULL));
|
||||
jalloc = make_test_job_alloc_with_host(7005ULL, "worker1", "slots", 2.0f);
|
||||
decoded
|
||||
= make_decoded_session(1000ULL, make_dispatch_entry_from_alloc(jalloc));
|
||||
|
||||
sim_reconcile_unaccounted_jobs(&sim, decoded, NULL);
|
||||
|
||||
TEST_ASSERT_NULL_MESSAGE(
|
||||
TEST_ASSERT_EQUAL_PTR_MESSAGE(
|
||||
jalloc, job->allocs,
|
||||
"a PEND-state job's recorded DISPATCH decision must now be "
|
||||
"captured (ownership TAKEOVER, identical pointer) just like an "
|
||||
"already-RUN job -- capture eligibility no longer depends on "
|
||||
"job->state");
|
||||
TEST_ASSERT_NOT_NULL_MESSAGE(
|
||||
job->accounts,
|
||||
"a non-RUN-state job must never be reconciled here, regardless of "
|
||||
"what recorded data exists for it this round");
|
||||
"job->accounts must be built (make_job_account()) from the "
|
||||
"captured allocation even though the job has not reached RUN yet");
|
||||
TEST_ASSERT_EQUAL_INT_MESSAGE(
|
||||
0, decoded->n_decisions,
|
||||
"the now-fully-consumed recorded entry must be removed from "
|
||||
"decoded_session->decisions, exactly as for an already-RUN job");
|
||||
|
||||
printf("test_reconcile_skips_non_run_state_job: PASS\n");
|
||||
printf("test_reconcile_captures_non_run_state_job_when_dispatch_"
|
||||
"recorded: PASS\n");
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
|
@ -839,7 +861,8 @@ int main(void)
|
|||
RUN_TEST(test_reconcile_is_safe_to_recheck_on_a_later_round);
|
||||
RUN_TEST(test_reconcile_skips_job_that_already_has_accounts);
|
||||
RUN_TEST(test_reconcile_ignores_non_dispatch_entry_with_matching_jobid);
|
||||
RUN_TEST(test_reconcile_skips_non_run_state_job);
|
||||
RUN_TEST(
|
||||
test_reconcile_captures_non_run_state_job_when_dispatch_recorded);
|
||||
RUN_TEST(
|
||||
test_reconcile_reconstructs_allocs_and_accounts_from_matching_dispatch);
|
||||
RUN_TEST(test_reconcile_compacts_via_shift_down_preserving_order);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue