feat(election-iomgr-refactor): extend ha_dispatch_gate for CTRL_PRIMARY_COMMITTING — task 3.1

This commit is contained in:
Rongsong Shen 2026-05-30 10:28:36 +00:00
parent 543981c505
commit e6135ea828
3 changed files with 256 additions and 0 deletions

View file

@ -511,6 +511,26 @@ int ha_dispatch_gate(ha_state_t *ha, int opcode)
return 0;
return -XCE_ERR_NOT_READY;
case CTRL_PRIMARY_COMMITTING:
/* Req 5.1, 5.2, 8.1: Primary won election but has not yet received
* majority replication ack. Allow only replication-related and
* administrative opcodes; deny job dispatch and queue management
* with XCE_ERR_NOT_READY. */
switch (opcode) {
case OPCode_heartbeat:
case OPCode_replConfig:
case OPCode_replConfigPush:
case OPCode_upgradeConfigAck:
case OPCode_hello:
case OPCode_walAck:
case OPCode_replEntry:
case OPCode_replAck:
case OPCode_replCatchUpDone:
return 0;
default:
return -XCE_ERR_NOT_READY;
}
case CTRL_STANDBY: {
/* Allow ops that standbys legitimately handle */
switch (opcode) {

View file

@ -540,6 +540,49 @@ static void test_dispatch_gate_init_allows_heartbeat(void)
printf("test_dispatch_gate_init_allows_heartbeat: PASS\n");
}
/* ── Task 3.1: dispatch gate CTRL_PRIMARY_COMMITTING ─────────────────────── */
static void test_dispatch_gate_committing_denies_job_ops(void)
{
/* Req 5.1, 8.1: When role is CTRL_PRIMARY_COMMITTING, primary-only
* job operations must be denied with XCE_ERR_NOT_READY.
* OPCode_jobsub is a representative job-submission opcode. */
ha_state_t ha;
ha_init(&ha, &g_dispatch_cfg, 0);
atomic_store_explicit(&ha.role, (int32_t)CTRL_PRIMARY_COMMITTING,
memory_order_release);
int rc = ha_dispatch_gate(&ha, OPCode_jobsub);
TEST_ASSERT_EQUAL_INT(-XCE_ERR_NOT_READY, rc);
ha_fini(&ha);
printf("test_dispatch_gate_committing_denies_job_ops: PASS\n");
}
static void test_dispatch_gate_committing_allows_repl_ops(void)
{
/* Req 5.2, 8.1: When role is CTRL_PRIMARY_COMMITTING, replication
* operations must be permitted (return 0).
* OPCode_replCatchUpDone is the key signal that ends the COMMITTING phase. */
ha_state_t ha;
ha_init(&ha, &g_dispatch_cfg, 0);
atomic_store_explicit(&ha.role, (int32_t)CTRL_PRIMARY_COMMITTING,
memory_order_release);
TEST_ASSERT_EQUAL_INT(0, ha_dispatch_gate(&ha, OPCode_replCatchUpDone));
TEST_ASSERT_EQUAL_INT(0, ha_dispatch_gate(&ha, OPCode_heartbeat));
TEST_ASSERT_EQUAL_INT(0, ha_dispatch_gate(&ha, OPCode_replConfig));
TEST_ASSERT_EQUAL_INT(0, ha_dispatch_gate(&ha, OPCode_replConfigPush));
TEST_ASSERT_EQUAL_INT(0, ha_dispatch_gate(&ha, OPCode_upgradeConfigAck));
TEST_ASSERT_EQUAL_INT(0, ha_dispatch_gate(&ha, OPCode_hello));
TEST_ASSERT_EQUAL_INT(0, ha_dispatch_gate(&ha, OPCode_walAck));
TEST_ASSERT_EQUAL_INT(0, ha_dispatch_gate(&ha, OPCode_replEntry));
TEST_ASSERT_EQUAL_INT(0, ha_dispatch_gate(&ha, OPCode_replAck));
ha_fini(&ha);
printf("test_dispatch_gate_committing_allows_repl_ops: PASS\n");
}
/* ── Test suite entry point ───────────────────────────────────────────── */
void test_ha_startup(void)
@ -587,4 +630,8 @@ void test_ha_startup(void)
/* Req 1.1 — dispatch gate allows heartbeat in CTRL_INIT */
RUN_TEST(test_dispatch_gate_init_allows_heartbeat);
/* Task 3.1 — dispatch gate: CTRL_PRIMARY_COMMITTING */
RUN_TEST(test_dispatch_gate_committing_denies_job_ops);
RUN_TEST(test_dispatch_gate_committing_allows_repl_ops);
}