fix(controller): job start_time/finish_time/run_time never set by apply-pump
apply_committed_entry()'s shared WAL_JOB_START/FINISH/STOP/RESUME/RUSAGE/ CKPT/PREASON dispatch case only ever called the generic, state-only apply_job_update_transition(j, state) -- start_time/finish_time/run_time were never touched, so `xcecli joblist` always showed StartTime=0 for RUN/DONE/EXIT jobs and FinishTime=0 for DONE jobs (EXIT jobs got a finish_time only via the separate, richer WAL_JOB_FAIL dispatch path). Fix is additive: stamp time(NULL) keyed on wal_type right after apply_job_update_transition() succeeds, still under the same lock(j, RTTI_LOCK_WRITE) -- WAL_JOB_START sets start_time, WAL_JOB_FINISH sets finish_time and derives run_time. No change to apply_job_update_transition()'s signature or the dispatch structure. Add test_ace_job_start_sets_start_time and test_ace_job_finish_sets_finish_time_and_run_time to test_apply_committed_entry.c, following the existing tace_seed_job fixture pattern. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
parent
008553e982
commit
5147396d0e
4 changed files with 90 additions and 1 deletions
|
|
@ -3714,7 +3714,9 @@ int apply_committed_entry(persist_t* p, uint32_t wal_type, uint64_t lsn,
|
|||
* apply_committed_entry for the full routing table and why this
|
||||
* does not dispatch to the richer type-specific apply_job_{start,
|
||||
* finish}_transition() cores (their parameter structs are not
|
||||
* present on this wire format). */
|
||||
* present on this wire format) — start_time/finish_time/run_time
|
||||
* are instead stamped directly below, keyed on wal_type, since
|
||||
* apply_job_update_transition() only ever touches `state`. */
|
||||
if (len < sizeof(wal_jobstate_t))
|
||||
return 0; /* undersized payload — skip, mirrors apply_wal_entry */
|
||||
|
||||
|
|
@ -3729,6 +3731,21 @@ int apply_committed_entry(persist_t* p, uint32_t wal_type, uint64_t lsn,
|
|||
lock(j, RTTI_LOCK_WRITE);
|
||||
job_transition_result_t result =
|
||||
apply_job_update_transition(j, (int)js->state);
|
||||
if (result == JOB_TRANSITION_APPLIED) {
|
||||
/* apply_job_update_transition() only carries {jobid, state} on
|
||||
* this wire shape (see the doc comment above) and never touches
|
||||
* start_time/finish_time/run_time itself — stamp them here,
|
||||
* keyed on wal_type, mirroring what the richer
|
||||
* apply_job_start_transition()/apply_job_finish_transition()
|
||||
* cores do for their own (currently unreachable on this dispatch
|
||||
* path) callers. */
|
||||
if (wal_type == WAL_JOB_START) {
|
||||
j->job.start_time = time(NULL);
|
||||
} else if (wal_type == WAL_JOB_FINISH) {
|
||||
j->job.finish_time = time(NULL);
|
||||
j->job.run_time = (int)(j->job.finish_time - j->job.start_time);
|
||||
}
|
||||
}
|
||||
unlock(j);
|
||||
|
||||
if (result != JOB_TRANSITION_APPLIED)
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@
|
|||
#include <stdarg.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
#include <unity/unity.h>
|
||||
|
||||
|
|
@ -402,6 +403,61 @@ test_ace_job_state_transition_rejects_backward_suppresses_notify(void)
|
|||
"notify: PASS\n");
|
||||
}
|
||||
|
||||
static void test_ace_job_start_sets_start_time(void)
|
||||
{
|
||||
tace_setup();
|
||||
|
||||
job_t* j = tace_seed_job(603, JOB_STAT_PEND);
|
||||
TEST_ASSERT_NOT_NULL(j);
|
||||
TEST_ASSERT_EQUAL_UINT64_MESSAGE(0, (uint64_t)j->job.start_time,
|
||||
"fixture must seed a job with start_time still unset");
|
||||
|
||||
wal_jobstate_t js = { .jobid = 603, .state = JOB_STAT_RUN };
|
||||
|
||||
time_t before = time(NULL);
|
||||
int rc = apply_committed_entry(&g_tace_p, WAL_JOB_START, 22, &js,
|
||||
sizeof(js));
|
||||
time_t after = time(NULL);
|
||||
|
||||
TEST_ASSERT_EQUAL_INT(0, rc);
|
||||
TEST_ASSERT_EQUAL_UINT32(JOB_STAT_RUN, j->job.state);
|
||||
TEST_ASSERT_TRUE_MESSAGE(
|
||||
(j->job.start_time >= before) && (j->job.start_time <= after),
|
||||
"WAL_JOB_START must stamp start_time to the apply-time clock");
|
||||
|
||||
tace_teardown();
|
||||
printf("test_ace_job_start_sets_start_time: PASS\n");
|
||||
}
|
||||
|
||||
static void test_ace_job_finish_sets_finish_time_and_run_time(void)
|
||||
{
|
||||
tace_setup();
|
||||
|
||||
job_t* j = tace_seed_job(604, JOB_STAT_RUN);
|
||||
TEST_ASSERT_NOT_NULL(j);
|
||||
j->job.start_time = 1000;
|
||||
|
||||
wal_jobstate_t js = { .jobid = 604, .state = JOB_STAT_DONE };
|
||||
|
||||
time_t before = time(NULL);
|
||||
int rc = apply_committed_entry(&g_tace_p, WAL_JOB_FINISH, 23, &js,
|
||||
sizeof(js));
|
||||
time_t after = time(NULL);
|
||||
|
||||
TEST_ASSERT_EQUAL_INT(0, rc);
|
||||
TEST_ASSERT_EQUAL_UINT32(JOB_STAT_DONE, j->job.state);
|
||||
TEST_ASSERT_TRUE_MESSAGE(
|
||||
(j->job.finish_time >= before) && (j->job.finish_time <= after),
|
||||
"WAL_JOB_FINISH must stamp finish_time to the apply-time clock");
|
||||
TEST_ASSERT_EQUAL_INT_MESSAGE((int)(j->job.finish_time - 1000),
|
||||
j->job.run_time,
|
||||
"run_time must be derived from the stamped finish_time minus the "
|
||||
"job's start_time");
|
||||
|
||||
tace_teardown();
|
||||
printf("test_ace_job_finish_sets_finish_time_and_run_time: PASS\n");
|
||||
}
|
||||
|
||||
/* ── WAL_QUEUE_CTRL ───────────────────────────────────────────────────── */
|
||||
|
||||
static void test_ace_queue_ctrl_updates_and_notifies(void)
|
||||
|
|
@ -1041,6 +1097,8 @@ void test_apply_committed_entry(void)
|
|||
RUN_TEST(test_ace_job_submit_duplicate_is_noop_no_extra_notify);
|
||||
RUN_TEST(test_ace_job_state_transition_applies_forward_and_notifies);
|
||||
RUN_TEST(test_ace_job_state_transition_rejects_backward_suppresses_notify);
|
||||
RUN_TEST(test_ace_job_start_sets_start_time);
|
||||
RUN_TEST(test_ace_job_finish_sets_finish_time_and_run_time);
|
||||
RUN_TEST(test_ace_queue_ctrl_updates_and_notifies);
|
||||
RUN_TEST(test_ace_worker_ctrl_join_restores_and_notifies);
|
||||
RUN_TEST(test_ace_worker_ctrl_update_applies_to_existing_worker);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue