feat(ha-commit-barrier-rollout): config barrier with production ACK ingestion (task 5.2 + r1)
configAck branch: per-push majority (acked_config_lsn >= push_tag, 1+count > n_peers/2 over r->ce->n_peers, n_peers<=1 immediate, ce==NULL -EINVAL); legacy >0 counting and n_active==0 shortcut dead. push_config_to_standbys returns the barrier result; upgrade failure -> send_upgrade_error (rc forwarded), no success ACK, no restart, committed_config_tag success-only. Remediation r1 (two CRITICAL review findings): - F1: wire production config-ACK ingestion — replconfigpushreplymsg decode branch in repl_ack_decode_and_dispatch -> repl_on_config_ack on the promoted-vote ep; + defensive cluster.c OPCode_reply case. Closes the unlanded half of ha-config-bootstrap 8.1; without this the barrier would brick every multi-member config upgrade. No schema change. - F2: keep the barrier off the iomgr thread — export push_config_transport_only (non-blocking) for the 5 ha.c + join.c streaming sites; barrier path now vtask-only (do_upgrade_config). Wire-path test drives real capnp ACK bytes through the production decode branch. 30/30 rollout, 6/6 repl_majority, 46/46 config_repl; census 0 FAIL; pre-existing fixture leak only (less than baseline).
This commit is contained in:
parent
9cdeba5816
commit
5a2fae1d37
12 changed files with 1034 additions and 399 deletions
|
|
@ -482,6 +482,35 @@ static int myreq_handler(vtask_t* task)
|
|||
}
|
||||
break;
|
||||
#endif
|
||||
case OPCode_reply:
|
||||
/* Config-push ACK arriving on an inbound standby endpoint (the
|
||||
* join.c-registered standby_endpoints channel — these eps reply on
|
||||
* the same connection the primary pushed on, so the ACK lands here
|
||||
* instead of peer_ctrl_msg_handler). Feed it to the replicator so
|
||||
* the configAck barrier can observe it (ha-commit-barrier-rollout
|
||||
* task 5.2 remediation r1; same ingestion as
|
||||
* repl_ack_decode_and_dispatch in ha.c — completes the unlanded
|
||||
* half of ha-config-bootstrap task 8.1). */
|
||||
if (request.body_which == Request_body_replymsg
|
||||
&& request.body.replymsg
|
||||
&& request.body.replymsg->data_which
|
||||
== RequestReply_data_replconfigpushreplymsg
|
||||
&& request.body.replymsg->data.replconfigpushreplymsg) {
|
||||
repl_config_push_reply_t *cack =
|
||||
request.body.replymsg->data.replconfigpushreplymsg;
|
||||
if (cack->accepted) {
|
||||
repl_on_config_ack(&c->persist.repl, ep, cack->version_tag);
|
||||
TRACE("myreq_handler: config ACK from inbound standby"
|
||||
" tag=%016" PRIx64, cack->version_tag);
|
||||
} else {
|
||||
WARN("myreq_handler: config push rejected by inbound standby"
|
||||
" (tag=%016" PRIx64 ") — ignoring", cack->version_tag);
|
||||
}
|
||||
rc = 0;
|
||||
break;
|
||||
}
|
||||
/* Any other reply body keeps the legacy unknown-opcode handling. */
|
||||
/* fall through */
|
||||
default:
|
||||
rc = -E_XCE_BAD_OPCODE;
|
||||
ERROR("Unknown opcode: %d", request.opcode);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue