feat(scheduler-dispatch-commit): handle_jobdispatch no longer duplicates dispatch-outcome reporting (task 4.1)

dispatch_a_job_() (tasks 3.1-3.3) now owns notification entirely for
every outcome -- notify_dispatch() on a retryable failure, mark_job_fail()'s
own hook chain on a terminal failure, nothing on success. handle_jobdispatch()'s
loop still unconditionally called notify_dispatch() itself for every job
regardless, producing two conflicting outcome reports for any failed
dispatch. Removed that caller-side call; the loop is now a thin
dispatch-and-free loop with no notification logic of its own.

New test_jobdispatch_no_double_notify.c drives a 3-job batch (success,
retryable, terminal) through handle_jobdispatch() and confirms exactly
one notification fires (from the retryable job only), not four.

Independently reviewed and approved. Confirmed handle_jobdispatch()'s
sole caller never depended on its notification behavior (always returns
0 unconditionally). Flagged that test_commit_barrier_reply.c's
test_jobdispatch_receipt_ack_no_wal_append is now stale for a second,
independent reason (notify count, not just WAL count) -- both left for
task 5.4 per Requirement 5.3.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Cxa1PmqAB5PyXfJaNvj8TN
This commit is contained in:
Rongsong Shen 2026-08-23 18:18:34 +00:00
parent 65390fb111
commit 7b3dfed56e
No known key found for this signature in database
GPG key ID: 5BCDAAE0123E9FE2
5 changed files with 374 additions and 10 deletions

View file

@ -1626,19 +1626,21 @@ int handle_jobdispatch(cluster_t* c, endpoint_t* ep, xce_request_t* request)
xce_reply(ep, c->myhost, &reply);
for (i = 0; i < dispatchmsg->njobs; i++) {
int rc1;
xce_job_alloc_t* alloc = NULL;
MOVE_PTR(alloc, dispatchmsg->allocs[i]);
rc1 = dispatch_a_job_(c, ep, alloc);
if (rc1 < 0) {
/* notify dispatch fail */
notify_dispatch(c, ep, alloc->jobid, rc1);
} else {
/* notify dispatch ok */
notify_dispatch(c, ep, alloc->jobid, 0);
}
/* scheduler-dispatch-commit task 4.1 (Req 3.1, 4.1, 4.2): reporting
* the dispatch outcome is now entirely owned by dispatch_a_job_()
* itself (tasks 3.1-3.3) -- it already calls notify_dispatch() on
* the retryable-failure path and relies on mark_job_fail()'s own
* hook chain for the terminal-failure path, never on success. This
* caller used to unconditionally call notify_dispatch() again for
* every job regardless of that outcome, producing a conflicting
* double report (e.g. both jobDispatchFail and schedFailJob for the
* same terminal failure). The return value has nothing left for
* this caller to act on. */
(void)dispatch_a_job_(c, ep, alloc);
free_JobAlloc_ptr(&(alloc));
}