feat(ha-term-safety): append config markers via unified log + derive committed config (task 4.2)

Wires do_upgrade_config_with_bytes to append WAL_CONFIG_MARKER through
raft_log_append (live term-stamped consensus record), demotes committed_config_tag
to a non-authoritative cache, and derives the committed config from the latest
committed marker. Preserves the derive across checkpoint compaction via an optional,
backward-compatible config-ref tail in the snapshot sentinel.
This commit is contained in:
Rongsong Shen 2026-06-22 10:34:10 +00:00
parent f447ad4183
commit c3201a2b1e
7 changed files with 883 additions and 21 deletions

View file

@ -277,6 +277,7 @@ static void test_classify_is_total_over_wal_entry_type(void)
{ WAL_JOB_PREASON, HOOK_DETAIL_CLRPREASON, "WAL_JOB_PREASON" },
{ WAL_QUEUE_CTRL, HOOK_DETAIL_QUEUE_UPDATE, "WAL_QUEUE_CTRL" },
{ WAL_WORKER_CTRL, HOOK_DETAIL_WORKER_DEAD, "WAL_WORKER_CTRL" },
{ WAL_CONFIG_MARKER, 0, "WAL_CONFIG_MARKER" },
{ WAL_CHECKPOINT, 0, "WAL_CHECKPOINT" },
};
size_t i;
@ -1167,6 +1168,8 @@ static zarray_t g_cb5_standbys;
static myconf_t g_cb5_myconf;
static char g_cb5_tmpdir[256];
static int g_cb5_have_tmpdir;
static char g_cb5_waldir[256]; /* started-persist WAL dir (task 4.2) */
static int g_cb5_have_waldir;
static void cb5_setup(void)
{
@ -1179,6 +1182,7 @@ static void cb5_setup(void)
memset(&g_cb5_req_priv, 0, sizeof(g_cb5_req_priv));
memset(&g_cb5_myconf, 0, sizeof(g_cb5_myconf));
g_cb5_have_tmpdir = 0;
g_cb5_have_waldir = 0;
g_cb5_c.myhost = &g_cb5_c.myhost_info;
g_cb5_c.myhost_info.name = (char *)"ctrl-cb5";
@ -1197,9 +1201,22 @@ static void cb5_setup(void)
}
g_cb5_c.ha.standby_endpoints = &g_cb5_standbys;
/* Replicator registry mirrors the push endpoints; wired engine carries
* n_peers=3 for the configAck majority denominator. */
TEST_ASSERT_EQUAL_INT(0, repl_init(&g_cb5_c.persist.repl));
/* Started persist so the live config-change path (config_commit_change →
* config_append_marker → ha_primary_log_append → persist_wal_async) can
* append the WAL_CONFIG_MARKER consensus record (ha-term-safety task 4.2).
* persist_init creates the replicator registry; we then mirror the push
* endpoints and wire the n_peers=3 engine (configAck majority denominator).
* A dedicated tmpdir keeps the WAL isolated from the myconf workdir. */
{
persist_config_t pcfg = persist_config_defaults();
pcfg.wal_sync_ms = 5000;
snprintf(g_cb5_waldir, sizeof(g_cb5_waldir), "/tmp/xce_cb5wal_XXXXXX");
TEST_ASSERT_NOT_NULL(mkdtemp(g_cb5_waldir));
g_cb5_have_waldir = 1;
persist_set_workdir(&g_cb5_c.persist, g_cb5_waldir, "ctrl-cb5");
TEST_ASSERT_EQUAL_INT(0, persist_init(&g_cb5_c.persist, &pcfg, &g_cb5_c));
TEST_ASSERT_EQUAL_INT(0, persist_start(&g_cb5_c.persist));
}
TEST_ASSERT_TRUE(repl_add_standby(&g_cb5_c.persist.repl,
&g_cb5_sb_ep[0], "cb5_a", 7500) >= 0);
TEST_ASSERT_TRUE(repl_add_standby(&g_cb5_c.persist.repl,
@ -1251,7 +1268,9 @@ static void cb5_teardown(void)
cb5_drain_ep(&g_cb5_sb_ep[1]);
cb5_drain_ep(&g_cb5_req_ep);
commit_engine_fini(&g_cb5_eng);
repl_fini(&g_cb5_c.persist.repl);
/* persist_fini calls repl_fini internally (started-persist fixture). */
persist_stop(&g_cb5_c.persist);
persist_fini(&g_cb5_c.persist);
zarray_fini(&g_cb5_standbys);
cbuf_fini(&g_cb5_c.wbuf);
free(g_cb5_myconf.conffile);
@ -1263,6 +1282,13 @@ static void cb5_teardown(void)
system(cmd);
g_cb5_have_tmpdir = 0;
}
if (g_cb5_have_waldir) {
char cmd[300];
snprintf(cmd, sizeof(cmd), "rm -rf %s", g_cb5_waldir);
system(cmd);
g_cb5_have_waldir = 0;
}
}
/* ── Reply observation (raw capnp parse of ep->outq packets) ────────────── */