chore: checkpoint all prior work for clean state
Captures all uncommitted work from ha-config-bootstrap, ha-heartbeat-liveness, and associated spec/tooling updates: - src: ha.c, ha.h, cluster.c, config_repl.c, myapp.c, raft.c — heartbeat liveness, RDHUP integration, committing phase fixes - tests: test_ha_role.c, test_config_repl.c, test_ha_rdhup_integration.c, test_p1_integration.c, test_p3_hardening.c, scheduler test - specs: election-iomgr-refactor, ha-heartbeat-liveness, ha-peer-connection-reuse, raft-library (new); ha-config-bootstrap and election-iomgr-refactor task/research updates - tooling: .wolf/ state, ha/data cluster fixtures, raft/raft.tla, src/build symlink, xce-build skill update
This commit is contained in:
parent
15bd291bdd
commit
e31673dd88
66 changed files with 122422 additions and 860 deletions
|
|
@ -68,6 +68,12 @@ int myapp_run(myconf_t *myconf)
|
|||
return rc;
|
||||
}
|
||||
|
||||
/* Wire raft_c before iomgr starts so raft_cb_persist can look up
|
||||
* candidate names when processing incoming vote requests during the
|
||||
* startup stagger nap. Without this, voted_for_name is cleared and the
|
||||
* already_voted check fails → unnecessary duplicate elections. */
|
||||
c.ha.raft_c = &c;
|
||||
|
||||
/* ── Step 2: SSL contexts ─────────────────────────────────────────────── */
|
||||
|
||||
/* Validate cert/key files early to fail fast before any network setup */
|
||||
|
|
@ -227,17 +233,30 @@ int myapp_run(myconf_t *myconf)
|
|||
nanosleep(&jitter, NULL);
|
||||
}
|
||||
|
||||
/* If we already voted for someone during the startup delay (incoming vote
|
||||
* request arrived from the higher-priority node that started first), skip
|
||||
* starting our own election — we'll become STANDBY via the election timeout
|
||||
* watchdog on the winner's side, or promote ourselves if no heartbeat arrives. */
|
||||
/* If a leader is already known after the startup stagger (either because
|
||||
* iomgr processed an incoming vote request and updated the raft term, or
|
||||
* because ctrlhello arrived on a promoted vote ep), skip starting our own
|
||||
* election. The voted_for_name check catches the synchronous vote-grant
|
||||
* path (iomgr was already running); the raft term + primary_ctrl_fd checks
|
||||
* catch the case where iomgr was NOT running during the nap (connections
|
||||
* queued in the kernel backlog) but the winner's ctrlhello has already
|
||||
* established the control channel. */
|
||||
{
|
||||
int leader_known = 0;
|
||||
pthread_mutex_lock(&c.ha.lock);
|
||||
int already_voted = (c.ha.voted_for_name[0] != '\0');
|
||||
if (c.ha.voted_for_name[0] != '\0')
|
||||
leader_known = 1;
|
||||
pthread_mutex_unlock(&c.ha.lock);
|
||||
if (already_voted) {
|
||||
INFO("myapp_run: already voted during startup delay — "
|
||||
"skipping own election, waiting for primary");
|
||||
if (!leader_known && c.ha.raft.term > 0)
|
||||
leader_known = 1;
|
||||
if (!leader_known && c.ha.primary_ctrl_fd >= 0)
|
||||
leader_known = 1;
|
||||
if (leader_known) {
|
||||
INFO("myapp_run: leader already known after startup delay "
|
||||
"(voted_for=%s, raft_term=%" PRIu64 ", primary_fd=%d) — "
|
||||
"skipping own election",
|
||||
c.ha.voted_for_name[0] ? c.ha.voted_for_name : "(none)",
|
||||
c.ha.raft.term, c.ha.primary_ctrl_fd);
|
||||
goto skip_election;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue