feat(ha-wal-replication): primary WalAckReply handler (task 4.1)

Handle incoming WalAckReply in repl_ack_decode_and_dispatch: extract
lsn+success, call repl_on_ack on success to update standby acked_lsn
and signal majority-ack waiter. NACK is WARN-logged with no state
change. Two unit tests verify positive path (acked_lsn updated, waiter
unblocked) and negative path (NACK leaves acked_lsn=0, wait times out).
This commit is contained in:
Rongsong Shen 2026-06-10 09:46:22 +00:00
parent 566c91cd8b
commit 861b746c84
2 changed files with 115 additions and 0 deletions

View file

@ -2661,6 +2661,24 @@ static int repl_ack_decode_and_dispatch(endpoint_t *ep, vote_ep_ctx_t *vctx)
ha_dispatch_repl_action_for_standby(ha, c, ep, peer_idx,
committed_tag, committed_lsn,
oldest_wal_lsn);
} else if (rep_s.data_which == RequestReply_data_walackreplymsg) {
/* Task 4.1: WAL ACK reply from standby — extract lsn + success,
* call repl_on_ack to update acked_lsn and signal majority waiter. */
struct WalAckReply war_raw;
memset(&war_raw, 0, sizeof(war_raw));
read_WalAckReply(&war_raw, rep_s.data.walackreplymsg);
uint64_t acked_lsn = (uint64_t)war_raw.lsn;
int success = war_raw.success ? 1 : 0;
capn_free(&capn_ctx);
if (success && c) {
repl_on_ack(&c->persist.repl, ep, acked_lsn);
TRACE("repl_ack_decode_and_dispatch: WAL ACK from standby"
" lsn=%lu success=1", (unsigned long)acked_lsn);
} else if (!success) {
WARN("repl_ack_decode_and_dispatch: WAL NACK from standby"
" lsn=%lu success=0 — ignoring", (unsigned long)acked_lsn);
}
} else {
capn_free(&capn_ctx);
}