feat(worker-rejoin-resync): reconcile unqueried job assignment (task 2.2)
Add record_job_reconcile_assign_fact(cluster_t*, job_t*, worker_t*, xce_job_state_entry_t*) to job.c: eagerly sets job->job.state to match the worker's reported outcome (mirroring dispatch_a_job_'s inline mutation, minus allocation fields -- there are none to set, job->job.allocs stays NULL per Requirement 4.8's documented scope). Calls the existing persist_submit_job_dispatch_fact(..., alloc=NULL) directly, then leaves the post-unlock persist_notify_job_updated_already_persisted() call to the caller, same convention as task 2.1. Fixes bug-1746 along the way: capnp_encode_joballoc() (persist.c, part of bug-1678's original fix, predates this feature) unconditionally dereferenced a NULL alloc -- never triggered before since dispatch_a_job_ (the only prior caller) always passes non-NULL. Fixed with a minimal guard producing a true zero-length buffer, matching apply_committed_entry's alloc_len > 0 decode gate exactly. This directly contradicted design.md's "tested, backward-compatible on both seams" claim (true only for decode, never actually exercised for encode) -- corrected in 4 places. 2 tests: applies-running-no-allocs-and-notifies, and a real restart- replay round trip (write to real disk, fresh persist_recover(), confirm jobid/host/state/NULL-allocs survive) -- proving this task's own "durably survives a restart replay" completion criterion literally, not just the in-memory mutation. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Y4M5MJM2zK6nU43da267Ku
This commit is contained in:
parent
b7ed6de2a1
commit
ecfb4c942f
7 changed files with 550 additions and 3 deletions
|
|
@ -13,6 +13,7 @@
|
|||
#include "myconf.h"
|
||||
#include "mylock.h"
|
||||
#include "netio.h"
|
||||
#include "typemap.h" /* xce_job_state_entry_t -- worker-rejoin-resync task 2.2 */
|
||||
#include "vtaskmgr.h"
|
||||
#include "worker.h"
|
||||
#include "xce/cluster_def.h"
|
||||
|
|
@ -211,6 +212,35 @@ extern job_transition_result_t apply_job_postdone_transition(job_t*);
|
|||
* call site. */
|
||||
extern int record_job_reconcile_pending_fact(cluster_t*, job_t*);
|
||||
|
||||
/* worker-rejoin-resync task 2.2 (Req 4.1, 4.3, 4.4, 4.7, 4.8, 7.1-7.3):
|
||||
* records a job the worker reports running that the controller has no
|
||||
* existing non-terminal record of ("unqueried extra", Req 3.6) as assigned
|
||||
* to the reporting worker `w`, matching `report`'s reported status --
|
||||
* dispatch_a_job_()'s own eager-mutation-plus-explicit-notify pattern, NOT
|
||||
* record_job_finish_fact's deferred one -- see design.md's "Controller:
|
||||
* job.c" Components section, and job.c's own doc comment on this function
|
||||
* for the full rationale (including why job->job.allocs is deliberately
|
||||
* left NULL, and why there is no separate "host assignment" field for this
|
||||
* function to set beyond job->job.state).
|
||||
*
|
||||
* Precondition: caller holds `job` under RTTI_LOCK_WRITE on entry and does
|
||||
* not release it until this call returns -- this function does not
|
||||
* lock/unlock `job` itself. Unlike record_job_reconcile_pending_fact above,
|
||||
* this function performs no backward-transition guard of its own: the
|
||||
* caller must only invoke it when the controller has no existing
|
||||
* non-terminal record of this job (Req 4.8's own trigger condition), so
|
||||
* there is nothing more-final to clobber.
|
||||
*
|
||||
* Always returns (int)JOB_TRANSITION_APPLIED -- this outcome has no
|
||||
* reject/no-op case (unlike record_job_reconcile_pending_fact's
|
||||
* REJECTED_BACKWARD/NOOP_DUPLICATE). Matching that sibling's contract, the
|
||||
* caller (not this function) must call
|
||||
* persist_notify_job_updated_already_persisted(c, job) itself, AFTER
|
||||
* releasing the write lock, exactly once -- omitting it reproduces bug-1679
|
||||
* at this call site. */
|
||||
extern int record_job_reconcile_assign_fact(cluster_t*, job_t*, worker_t*,
|
||||
xce_job_state_entry_t*);
|
||||
|
||||
extern int on_job_start(cluster_t*, job_pidinfo_t*);
|
||||
extern int on_job_finish(cluster_t*, xce_jobfinish_t*);
|
||||
extern int on_job_fail(cluster_t*, job_failinfo_t*);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue