feat(ha-single-leader-role): delete force-promotion watchdog + convergence/ack machinery (task 4.1)
This commit is contained in:
parent
b7b951b9e7
commit
a5bf86112a
10 changed files with 95 additions and 1869 deletions
|
|
@ -50,6 +50,14 @@ static int stub_phase2(void *c) { (void)c; g_phase2_calls++; return 0;
|
|||
static int stub_push_config(void *c) { (void)c; g_push_config_calls++; return 0; }
|
||||
static int stub_ctrlhello(void *c) { (void)c; g_ctrlhello_calls++; return 0; }
|
||||
|
||||
/* ha-single-leader-role task 4.1: the replication-ack handler was deleted (the
|
||||
* ack-counting force-promotion machinery is gone — promotion is driven solely
|
||||
* by the heartbeat decision loop + per-entry majority ack). No shim is added
|
||||
* (design §"Transitional-State Deletions": no replacements, no shims). The
|
||||
* ack-driven-promotion cases were deleted; the surviving state-entry cases no
|
||||
* longer call it (production ha_elect_evaluate_and_signal now lands the winner
|
||||
* directly per task 5.1 territory). */
|
||||
|
||||
/* ── Shared HA config ───────────────────────────────────────────────────── */
|
||||
|
||||
static ha_config_t g_cfg = {
|
||||
|
|
@ -196,50 +204,11 @@ static void test_rdhup_full_path_reaches_committing(void)
|
|||
}
|
||||
|
||||
/* ═══════════════════════════════════════════════════════════════════════════
|
||||
* Test 2: RDHUP → COMMITTING → PRIMARY via ha_repl_ack_received
|
||||
*
|
||||
* Req 8.2: majority ack in COMMITTING → CTRL_PRIMARY
|
||||
* Req 6.5: promoted standby serves traffic (dispatch gate opens)
|
||||
* Test 2 (RDHUP → PRIMARY via replication-ack handler) DELETED — ha-single-leader-role
|
||||
* task 4.1. Subject was the deleted ack-driven force-promotion machinery
|
||||
* (the replication-ack handler); nothing left to verify. No shim, no retarget
|
||||
* (design §"Transitional-State Deletions").
|
||||
* ═════════════════════════════════════════════════════════════════════════ */
|
||||
static void test_rdhup_committing_to_primary_on_ack(void)
|
||||
{
|
||||
install_stubs();
|
||||
|
||||
cluster_t c;
|
||||
myconf_t myconf;
|
||||
make_cluster(&c, &myconf, "ctrl-a");
|
||||
|
||||
TEST_ASSERT_EQUAL_INT(0, ha_init(&c.ha, &g_cfg, 0));
|
||||
ha_do_demote(&c.ha);
|
||||
c.ha.phase2_done = 1;
|
||||
c.ha.n_peers = 1; /* 2-node cluster: quorum=1, threshold=0 */
|
||||
|
||||
g_rdhup_state.c = &c;
|
||||
ha_rdhup_election_hook = rdhup_election_drives_evaluate;
|
||||
|
||||
int sv[2];
|
||||
TEST_ASSERT_EQUAL_INT(0, socketpair(AF_UNIX, SOCK_STREAM, 0, sv));
|
||||
c.ha.primary_ctrl_fd = sv[0];
|
||||
|
||||
/* Fire RDHUP → should reach CTRL_PRIMARY_COMMITTING */
|
||||
ha_on_primary_ctrl_fd_rdhup(&c.ha, &c);
|
||||
close(sv[1]);
|
||||
|
||||
int role = (int)atomic_load_explicit(&c.ha.role, memory_order_acquire);
|
||||
TEST_ASSERT_EQUAL_INT((int)CTRL_PRIMARY_COMMITTING, role);
|
||||
|
||||
/* n_peers=1 → quorum=(1+2)/2=1 → threshold=0 → first ack promotes.
|
||||
* ha_repl_ack_received increments count; acks(1) >= quorum-1(0) → promote. */
|
||||
ha_repl_ack_received(&c.ha, &c);
|
||||
|
||||
role = (int)atomic_load_explicit(&c.ha.role, memory_order_acquire);
|
||||
TEST_ASSERT_EQUAL_INT_MESSAGE((int)CTRL_PRIMARY, role,
|
||||
"ha_repl_ack_received must drive COMMITTING → CTRL_PRIMARY on quorum ack (Req 8.2)");
|
||||
|
||||
clear_stubs();
|
||||
ha_fini(&c.ha);
|
||||
printf("test_rdhup_committing_to_primary_on_ack: PASS (role=%d==CTRL_PRIMARY)\n", role);
|
||||
}
|
||||
|
||||
/* ═══════════════════════════════════════════════════════════════════════════
|
||||
* Test 3: RDHUP in single-node cluster → immediate PRIMARY (no COMMITTING)
|
||||
|
|
@ -273,15 +242,11 @@ static void test_rdhup_single_node_reaches_primary(void)
|
|||
ha_on_primary_ctrl_fd_rdhup(&c.ha, &c);
|
||||
close(sv[1]);
|
||||
|
||||
/* n_peers=0 → quorum=(0+2)/2=1 → threshold=0 → acks(0) >= 0 → promoted inline */
|
||||
/* n_peers=0 → ha_elect_evaluate_and_signal single-node shortcircuit lands
|
||||
* CTRL_PRIMARY directly (no transitional COMMITTING, no ack machinery —
|
||||
* ha-single-leader-role). The old replication-ack fallback was excised
|
||||
* (function deleted task 4.1); the PRIMARY assertion stands on its own. */
|
||||
int role = (int)atomic_load_explicit(&c.ha.role, memory_order_acquire);
|
||||
/* Single-node: no standbys to ack, committing_timeout degrades to PRIMARY.
|
||||
* The committing timeout is 10s; for single-node we call ha_repl_ack_received
|
||||
* once to simulate the degraded-mode zero-threshold promotion (threshold=0). */
|
||||
if (role == (int)CTRL_PRIMARY_COMMITTING) {
|
||||
ha_repl_ack_received(&c.ha, &c);
|
||||
role = (int)atomic_load_explicit(&c.ha.role, memory_order_acquire);
|
||||
}
|
||||
TEST_ASSERT_EQUAL_INT_MESSAGE((int)CTRL_PRIMARY, role,
|
||||
"single-node RDHUP path must reach CTRL_PRIMARY (Req 9.1)");
|
||||
|
||||
|
|
@ -291,52 +256,12 @@ static void test_rdhup_single_node_reaches_primary(void)
|
|||
}
|
||||
|
||||
/* ═══════════════════════════════════════════════════════════════════════════
|
||||
* Test 4: 3-node cluster RDHUP — two acks needed, premature ack stays COMMITTING
|
||||
*
|
||||
* Req 8.2: acks < quorum-1 → stays COMMITTING; acks >= quorum-1 → PRIMARY
|
||||
* 3-node (n_peers=2): quorum=2, threshold=1 → need 1 ack to promote
|
||||
* Test 4 (3-node RDHUP — ack-driven promotion) DELETED — ha-single-leader-role
|
||||
* task 4.1. Subject was the deleted ack-counting promotion machinery
|
||||
* (the replication-ack handler drives COMMITTING → PRIMARY on threshold acks);
|
||||
* the mechanism is gone, nothing left to verify. No shim (design §"Transitional-
|
||||
* State Deletions").
|
||||
* ═════════════════════════════════════════════════════════════════════════ */
|
||||
static void test_rdhup_3node_one_ack_promotes(void)
|
||||
{
|
||||
install_stubs();
|
||||
|
||||
cluster_t c;
|
||||
myconf_t myconf;
|
||||
make_cluster(&c, &myconf, "ctrl-a");
|
||||
myconf.peers_cfg.candidates_count = 3;
|
||||
snprintf(myconf.peers_cfg.candidates[2].name,
|
||||
sizeof(myconf.peers_cfg.candidates[2].name), "ctrl-c");
|
||||
myconf.peers_cfg.candidates[2].port = 7003;
|
||||
|
||||
TEST_ASSERT_EQUAL_INT(0, ha_init(&c.ha, &g_cfg, 0));
|
||||
ha_do_demote(&c.ha);
|
||||
c.ha.phase2_done = 1;
|
||||
c.ha.n_peers = 2; /* 3-node: quorum=2, threshold=1 */
|
||||
|
||||
g_rdhup_state.c = &c;
|
||||
ha_rdhup_election_hook = rdhup_election_drives_evaluate;
|
||||
|
||||
int sv[2];
|
||||
TEST_ASSERT_EQUAL_INT(0, socketpair(AF_UNIX, SOCK_STREAM, 0, sv));
|
||||
c.ha.primary_ctrl_fd = sv[0];
|
||||
|
||||
ha_on_primary_ctrl_fd_rdhup(&c.ha, &c);
|
||||
close(sv[1]);
|
||||
|
||||
int role = (int)atomic_load_explicit(&c.ha.role, memory_order_acquire);
|
||||
TEST_ASSERT_EQUAL_INT_MESSAGE((int)CTRL_PRIMARY_COMMITTING, role,
|
||||
"3-node RDHUP must enter CTRL_PRIMARY_COMMITTING before acks");
|
||||
|
||||
/* First ack: count=1 >= threshold=1 → promotes */
|
||||
ha_repl_ack_received(&c.ha, &c);
|
||||
role = (int)atomic_load_explicit(&c.ha.role, memory_order_acquire);
|
||||
TEST_ASSERT_EQUAL_INT_MESSAGE((int)CTRL_PRIMARY, role,
|
||||
"3-node: first ack (count=1 >= threshold=1) must promote to CTRL_PRIMARY (Req 8.2)");
|
||||
|
||||
clear_stubs();
|
||||
ha_fini(&c.ha);
|
||||
printf("test_rdhup_3node_one_ack_promotes: PASS (role=%d==CTRL_PRIMARY)\n", role);
|
||||
}
|
||||
|
||||
/* ═══════════════════════════════════════════════════════════════════════════
|
||||
* Test 5: config push and ctrlhello hooks fire during COMMITTING entry
|
||||
|
|
@ -422,9 +347,10 @@ static void test_rdhup_primary_dispatch_gate_opens(void)
|
|||
ha_on_primary_ctrl_fd_rdhup(&c.ha, &c);
|
||||
close(sv[1]);
|
||||
|
||||
/* Drive to CTRL_PRIMARY via ack */
|
||||
ha_repl_ack_received(&c.ha, &c);
|
||||
|
||||
/* ha-single-leader-role: ha_elect_evaluate_and_signal lands the winner in
|
||||
* CTRL_PRIMARY directly (no transitional COMMITTING, no ack machinery). The
|
||||
* old replication-ack drive-step was excised (function deleted task 4.1);
|
||||
* the dispatch-gate assertion below is the subject of this case. */
|
||||
int role = (int)atomic_load_explicit(&c.ha.role, memory_order_acquire);
|
||||
TEST_ASSERT_EQUAL_INT((int)CTRL_PRIMARY, role);
|
||||
|
||||
|
|
@ -450,9 +376,11 @@ static void test_rdhup_primary_dispatch_gate_opens(void)
|
|||
void test_ha_rdhup_integration(void)
|
||||
{
|
||||
RUN_TEST(test_rdhup_full_path_reaches_committing);
|
||||
RUN_TEST(test_rdhup_committing_to_primary_on_ack);
|
||||
/* test_rdhup_committing_to_primary_on_ack deleted (ha-single-leader-role 4.1:
|
||||
* ack-driven promotion machinery removed, no shim) */
|
||||
RUN_TEST(test_rdhup_single_node_reaches_primary);
|
||||
RUN_TEST(test_rdhup_3node_one_ack_promotes);
|
||||
/* test_rdhup_3node_one_ack_promotes deleted (ha-single-leader-role 4.1:
|
||||
* ack-counting promotion machinery removed, no shim) */
|
||||
RUN_TEST(test_rdhup_committing_fires_replication_hooks);
|
||||
RUN_TEST(test_rdhup_primary_dispatch_gate_opens);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue