feat(controller-status): carry election time on the heartbeat (task 7.3)
The primary echoes its own last_known_elected_at_ms on every outgoing heartbeat (threaded through xce_ha_heartbeat_req's existing scalar-arg plumbing, alongside term/committed_lsn/committed_config_tag); a standby processing a received heartbeat (ha_consume_heartbeat_committed, the sole production call site) stores it unconditionally into its own last_known_elected_at_ms, reconcile-free -- no other HA field moves. ha_observe_heartbeat_committed itself is untouched; the new store sits next to its call site, not inside it. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RLSNJhNoULvVcUhXEFafQC
This commit is contained in:
parent
21ae00b375
commit
30adc52ea3
9 changed files with 252 additions and 33 deletions
|
|
@ -29,13 +29,15 @@ static void test_hostctrl_req_null_ep(void)
|
|||
* (free_packet + FREEUP), so the caller must NOT free the returned pkt — it is
|
||||
* consumed by the subsequent xce_decode(). Mirrors the test_wal_wire pattern. */
|
||||
static io_packet_t *encode_heartbeat(uint64_t term, uint64_t committed_lsn,
|
||||
uint64_t committed_config_tag)
|
||||
uint64_t committed_config_tag,
|
||||
uint64_t elected_at_ms)
|
||||
{
|
||||
heartbeat_msg_t hb = {
|
||||
.sender_priority = 0,
|
||||
.term = term,
|
||||
.committed_lsn = committed_lsn,
|
||||
.committed_config_tag = committed_config_tag,
|
||||
.elected_at_ms = elected_at_ms,
|
||||
};
|
||||
xce_request_t request = {
|
||||
.opcode = OPCode_nop,
|
||||
|
|
@ -53,26 +55,28 @@ static io_packet_t *encode_heartbeat(uint64_t term, uint64_t committed_lsn,
|
|||
static void test_ha_heartbeat_req_null_ep(void)
|
||||
{
|
||||
/* Mirror the nop sender's NULL-endpoint guard. */
|
||||
int rc = xce_ha_heartbeat_req(NULL, 1, 1, 1);
|
||||
int rc = xce_ha_heartbeat_req(NULL, 1, 1, 1, 1);
|
||||
TEST_ASSERT_EQUAL_INT(-EINVAL, rc);
|
||||
}
|
||||
|
||||
static void test_ha_heartbeat_req_roundtrip_fields(void)
|
||||
{
|
||||
/* Arrange/Act: encode a heartbeat carrying a committed position, decode. */
|
||||
io_packet_t *pkt = encode_heartbeat(7, 9, 4);
|
||||
/* Arrange/Act: encode a heartbeat carrying a committed position and an
|
||||
* election time (Req 12.2), decode. */
|
||||
io_packet_t *pkt = encode_heartbeat(7, 9, 4, 12345);
|
||||
|
||||
xce_request_t req;
|
||||
memset(&req, 0, sizeof(req));
|
||||
TEST_ASSERT_EQUAL_INT(0, xce_decode(pkt, &req)); /* consumes/frees pkt */
|
||||
|
||||
/* Assert: OP_nop + heartbeatmsg arm with the three fields intact. */
|
||||
/* Assert: OP_nop + heartbeatmsg arm with all four fields intact. */
|
||||
TEST_ASSERT_EQUAL_INT(OPCode_nop, req.opcode);
|
||||
TEST_ASSERT_EQUAL_INT(Request_body_heartbeatmsg, req.body_which);
|
||||
TEST_ASSERT_NOT_NULL(req.body.heartbeatmsg);
|
||||
TEST_ASSERT_EQUAL_UINT64(7, req.body.heartbeatmsg->term);
|
||||
TEST_ASSERT_EQUAL_UINT64(9, req.body.heartbeatmsg->committed_lsn);
|
||||
TEST_ASSERT_EQUAL_UINT64(4, req.body.heartbeatmsg->committed_config_tag);
|
||||
TEST_ASSERT_EQUAL_UINT64(12345, req.body.heartbeatmsg->elected_at_ms);
|
||||
|
||||
xce_free_request(&req);
|
||||
printf("test_ha_heartbeat_req_roundtrip_fields: PASS\n");
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue