feat(worker-rejoin-resync): task 6.2 - route job-state report to reconciliation
Add OPCode_jobStateReport dispatch in myreq_handler, reassembling a report across multiple incoming pages before handing it to task 3.2's resync_apply_report() exactly once - proven via a test-only call counter, not just end-state equivalence (a double-apply could pass an end-state check if idempotent). Standby-redirect investigation (Req 8.1/8.3): confirmed ha_dispatch_gate already redirects every rejected opcode uniformly, so no opcode-specific code was needed for that. OPCode_jobStateQuery has no controller-side receive path at all (only sent, never received) so needed no gate change either. That same investigation found a different, more consequential gap: fixes bug-1753, ha_dispatch_gate's quorum-loss fact-admission allowlist (OPCode_notify/update/setpreason/clrpreason) was missing OPCode_jobStateReport, so a report arriving during a transient quorum-loss window - this feature's own core failover scenario - would be rejected outright with no retry (worker sends fire-and-forget). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Y4M5MJM2zK6nU43da267Ku
This commit is contained in:
parent
a3d12d37d9
commit
9f655c61c7
12 changed files with 1178 additions and 12 deletions
|
|
@ -25,6 +25,7 @@
|
|||
|
||||
#include "jobj.h"
|
||||
#include "resobj.h"
|
||||
#include "resync.h" /* worker-rejoin-resync task 6.2: resync_handle_report_page */
|
||||
#include "utils.h"
|
||||
#include "worker.h"
|
||||
#include "xce/errnox.h"
|
||||
|
|
@ -237,6 +238,58 @@ static int handle_snapshot_transfer(cluster_t *c, xce_request_t *req)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* handle_jobstatereport: dispatch handler for OPCode_jobStateReport
|
||||
* (worker-rejoin-resync task 6.2, Req 8.1, 8.3) -- the worker's answer to a
|
||||
* job-state reconciliation query the controller sent it (worker.c's
|
||||
* worker_send_resync_query(), task 6.1). Resolves the reporting worker from
|
||||
* the inbound connection via get_ep_worker() (misc.c) -- the same ep-
|
||||
* >worker_t resolution on_worker_join() already uses to SEND that query
|
||||
* (worker.c) -- then delegates wire-page reassembly + apply to resync_
|
||||
* handle_report_page() (resync.c, task 6.2), which reassembles a report
|
||||
* that arrives across multiple pages and hands the complete result to
|
||||
* resync_apply_report() (task 3.2) exactly once, never once per page.
|
||||
*
|
||||
* Fire-and-forget from the worker's side (xce_job_state_report_req(),
|
||||
* request.c -- the same fire-and-forget shape xce_job_state_query_req()
|
||||
* already uses to SEND the query) -- no reply is expected or sent back,
|
||||
* matching OPCode_walCatchupEntry/OPCode_snapshotTransfer's existing
|
||||
* no-reply convention immediately above for this class of one-way,
|
||||
* already-happened-fact daemon-to-daemon message.
|
||||
*
|
||||
* A page from a connection that does not resolve to a known worker
|
||||
* (get_ep_worker() returns NULL -- e.g. a stale/torn-down connection racing
|
||||
* teardown) is logged and dropped: there is no worker_t to reassemble or
|
||||
* apply this report against, and nothing to reply to either way. */
|
||||
static int handle_jobstatereport(cluster_t* c, endpoint_t* ep,
|
||||
xce_request_t* req)
|
||||
{
|
||||
xce_job_state_report_t* page = req->body.jobstatereportmsg;
|
||||
worker_t* w;
|
||||
int rc;
|
||||
|
||||
if (page == NULL)
|
||||
return 0;
|
||||
|
||||
w = get_ep_worker(c, ep);
|
||||
if (w == NULL) {
|
||||
WARN("handle_jobstatereport: endpoint %p does not resolve to a "
|
||||
"known worker -- dropping report page (pos=%d count=%d "
|
||||
"ntotal=%d)", (void*)ep, page->pos, page->count, page->n_total);
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
rc = resync_handle_report_page(c, w, page);
|
||||
if (rc < 0)
|
||||
ERROR("handle_jobstatereport: worker %s: failed to reassemble/apply "
|
||||
"report page (pos=%d count=%d ntotal=%d) rc=%d",
|
||||
(w->host.name != NULL) ? w->host.name : "?", page->pos,
|
||||
page->count, page->n_total, rc);
|
||||
|
||||
dereference(w);
|
||||
|
||||
return (rc < 0) ? rc : 0;
|
||||
}
|
||||
|
||||
/* ---- OPCode_schedAdmin: forward-and-block-for-reply support (task 10.1) --
|
||||
*
|
||||
* The controller is a stateless pass-through for OPCode_schedAdmin: it
|
||||
|
|
@ -522,6 +575,29 @@ static int myreq_handler(vtask_t* task)
|
|||
case OPCode_jobdispatch:
|
||||
rc = handle_jobdispatch(c, ep, &request);
|
||||
break;
|
||||
case OPCode_jobStateReport:
|
||||
/* worker-rejoin-resync task 6.2 (Req 8.1, 8.3): the controller only
|
||||
* ever RECEIVES OPCode_jobStateReport (worker -> controller) -- the
|
||||
* sibling opcode, OPCode_jobStateQuery, flows controller -> worker
|
||||
* only (sent by worker_send_resync_query(), worker.c) and is never
|
||||
* inbound to this switch; the worker's own myreq_handler
|
||||
* (controller_connector.c, task 4.3) is what dispatches THAT one.
|
||||
* No standby-redirect handling is added here: ha_dispatch_gate()
|
||||
* above already rejects this opcode on every non-primary role with
|
||||
* -XCE_ERR_STANDBY (it is deliberately absent from the CTRL_STANDBY
|
||||
* allow-list, ha.c) BEFORE this switch is ever reached, and the
|
||||
* generic post-gate rejection block a few lines up already
|
||||
* populates the redirect hint (bug-1700) for exactly that status --
|
||||
* so a standby-received report is redirected the same way every
|
||||
* other primary-only opcode already is, with zero opcode-specific
|
||||
* code needed here. See ha.c's CTRL_PRIMARY-without-quorum branch
|
||||
* for the ADJACENT, genuinely-needed fix this task found: admitting
|
||||
* this opcode as a fact-bearing op there (alongside OPCode_notify)
|
||||
* so a report is never rejected outright during a transient quorum
|
||||
* loss (bug-396's exact failure mode, which this whole feature
|
||||
* exists to correct). */
|
||||
rc = handle_jobstatereport(c, ep, &request);
|
||||
break;
|
||||
case OPCode_jobsub:
|
||||
rc = handle_jobsubmit(c, ep, &request);
|
||||
break;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue