feat(ha-wal-replication): standby WAL ACK reply (tasks 3.1-3.3)
Standby sends WalAckReply via xce_reply after each successfully applied WAL entry. ha_apply_wal_catchup_entry signature extended with endpoint_t* and cluster_t* parameters. walackreplymsg union arm added to RequestReply capnp schema and xce_reply_t. Error entries skip ACK. Dispatch gate test confirms OPCode_walCatchupEntry allowed in CTRL_STANDBY/ELECTING/INIT. Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
81dbc4d7b4
commit
566c91cd8b
8 changed files with 304 additions and 60 deletions
|
|
@ -1008,8 +1008,33 @@ static int ha_apply_single_entry(persist_t *p, wal_catchup_entry_t *e)
|
|||
return apply_wal_entry(p, &hdr, e->raw_payload);
|
||||
}
|
||||
|
||||
/* ha_send_wal_ack_reply: send WalAckReply {term, lsn, success=1} back to
|
||||
* the primary over ep. Skipped when ep or c is NULL (test/offline path).
|
||||
* Task 3.1 (ha-wal-replication): ACK each successfully applied WAL entry. */
|
||||
static void ha_send_wal_ack_reply(ha_state_t *ha, struct endpoint_t *ep,
|
||||
cluster_t *c, uint64_t lsn)
|
||||
{
|
||||
if (!ep || !c)
|
||||
return;
|
||||
|
||||
wal_ack_reply_t ack;
|
||||
ack.term = (uint64_t)atomic_load_explicit(&ha->term, memory_order_acquire);
|
||||
ack.lsn = lsn;
|
||||
ack.success = 1;
|
||||
|
||||
xce_reply_t reply;
|
||||
memset(&reply, 0, sizeof(reply));
|
||||
reply.opcode = OPCode_walAck;
|
||||
reply.status = 0;
|
||||
reply.data_which = RequestReply_data_walackreplymsg;
|
||||
reply.data.walackreplymsg = &ack;
|
||||
|
||||
xce_reply(ep, c->myhost, &reply);
|
||||
}
|
||||
|
||||
int ha_apply_wal_catchup_entry(ha_state_t *ha, persist_t *p,
|
||||
wal_catchup_entry_t *entry)
|
||||
wal_catchup_entry_t *entry,
|
||||
struct endpoint_t *ep, cluster_t *c)
|
||||
{
|
||||
if (!ha || !p || !entry)
|
||||
return -EINVAL;
|
||||
|
|
@ -1037,9 +1062,13 @@ int ha_apply_wal_catchup_entry(ha_state_t *ha, persist_t *p,
|
|||
"for batch index %d lsn=%" PRIu64 " type=%u rc=%d "
|
||||
"— skipping entry",
|
||||
i, sub->lsn, (unsigned)sub->entry_type, rc);
|
||||
/* Task 3.2: no ACK for failed entries */
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Task 3.1: ACK each successfully applied sub-entry */
|
||||
ha_send_wal_ack_reply(ha, ep, c, sub->lsn);
|
||||
|
||||
last_good_lsn = sub->lsn;
|
||||
had_good = 1;
|
||||
}
|
||||
|
|
@ -1058,12 +1087,16 @@ int ha_apply_wal_catchup_entry(ha_state_t *ha, persist_t *p,
|
|||
ERROR("ha_apply_wal_catchup_entry: apply_wal_entry failed for "
|
||||
"lsn=%" PRIu64 " type=%u rc=%d — skipping entry",
|
||||
entry->lsn, (unsigned)entry->entry_type, rc);
|
||||
/* Task 3.2: no ACK on apply failure */
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* Advance applied_lsn atomically (lsn+1 mirrors persist->current_lsn
|
||||
* after a successful apply). */
|
||||
ha_advance_applied_lsn(ha, entry->lsn + 1);
|
||||
|
||||
/* Task 3.1: ACK the successfully applied single entry */
|
||||
ha_send_wal_ack_reply(ha, ep, c, entry->lsn);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue