feat(ha-convergence-recovery): self-restart primitive + demotion convergence (task 2.2)
This commit is contained in:
parent
c8e55947c2
commit
09103a3141
7 changed files with 337 additions and 43 deletions
|
|
@ -369,7 +369,7 @@ static void test_demotion_from_standby_no_truncation_no_restart(void)
|
|||
printf("test_demotion_from_standby_no_truncation_no_restart: checked\n");
|
||||
}
|
||||
|
||||
/* Regression: demotion from ELECTING/INIT must NOT truncate or restart. */
|
||||
/* Regression: demotion from ELECTING must NOT truncate or restart. */
|
||||
static void test_demotion_from_electing_no_truncation_no_restart(void)
|
||||
{
|
||||
dc_setup("electing", /*n_peers=*/3, /*n_standbys=*/2,
|
||||
|
|
@ -403,6 +403,42 @@ static void test_demotion_from_electing_no_truncation_no_restart(void)
|
|||
printf("test_demotion_from_electing_no_truncation_no_restart: checked\n");
|
||||
}
|
||||
|
||||
/* Regression: demotion from INIT must NOT truncate or restart (mirror of the
|
||||
* ELECTING case — a CTRL_INIT node has no registered persistence hooks and no
|
||||
* provisional suffix, so the was-PRIMARY convergence branch must not fire). */
|
||||
static void test_demotion_from_init_no_truncation_no_restart(void)
|
||||
{
|
||||
dc_setup("init", /*n_peers=*/3, /*n_standbys=*/2,
|
||||
/*appended_lsn=*/9, /*n_vcpus=*/8);
|
||||
atomic_store(&g_dc.persist.committed_lsn, 4);
|
||||
|
||||
/* No registered hooks on a starting node; force role to INIT. */
|
||||
TEST_ASSERT_EQUAL_INT(0, ha_demote_to_standby(&g_dc)); /* clears hooks */
|
||||
atomic_store_explicit(&g_dc.ha.role, (int32_t)CTRL_INIT,
|
||||
memory_order_release);
|
||||
|
||||
ha_restart_hook = dc_restart_hook;
|
||||
ha_fatal_hook = dc_fatal_hook;
|
||||
|
||||
uint64_t tip_before = g_dc.persist.current_lsn;
|
||||
int tasks_before = dc_task_count(&g_dc.delaymgr);
|
||||
|
||||
/* Act. */
|
||||
raft_cb_become_follower_with_cluster_for_test(&g_dc, /*term=*/8);
|
||||
|
||||
/* Assert. */
|
||||
TEST_ASSERT_EQUAL_INT_MESSAGE(tasks_before,
|
||||
dc_task_count(&g_dc.delaymgr),
|
||||
"demotion from INIT must schedule NO convergence task (regression)");
|
||||
TEST_ASSERT_EQUAL_UINT64_MESSAGE(tip_before, g_dc.persist.current_lsn,
|
||||
"demotion from INIT must NOT truncate the WAL (regression)");
|
||||
TEST_ASSERT_EQUAL_INT_MESSAGE(0, atomic_load(&g_restart_calls),
|
||||
"demotion from INIT must NOT self-restart (regression)");
|
||||
|
||||
dc_teardown();
|
||||
printf("test_demotion_from_init_no_truncation_no_restart: checked\n");
|
||||
}
|
||||
|
||||
/* 1.7/2.4 (integration, in-process half): append a committed prefix + an
|
||||
* uncommitted suffix, run the demotion seam, then replay the SURVIVING WAL into
|
||||
* a FRESH persist context. The replayed state must contain the committed prefix
|
||||
|
|
@ -492,6 +528,7 @@ void test_demotion_convergence(void)
|
|||
RUN_TEST(test_self_restart_failure_invokes_fatal_hook);
|
||||
RUN_TEST(test_demotion_from_standby_no_truncation_no_restart);
|
||||
RUN_TEST(test_demotion_from_electing_no_truncation_no_restart);
|
||||
RUN_TEST(test_demotion_from_init_no_truncation_no_restart);
|
||||
RUN_TEST(test_demotion_replay_yields_committed_only);
|
||||
#else
|
||||
printf("test_demotion_convergence: SKIP (non-test build)\n");
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue