fix(ha-term-safety): bug-828 partial — revive dead safe-commit-from-votes + advertise real durable tip
Clean failover was truncating committed jobs because the post-election safe-commit-from-votes computation was dead: vote_reply_dispatch decoded each granting voter's advertised peerLastLogLsn but discarded it, so ha_compute_safe _committed_lsn saw only the self-vote (the 'from 1 granted voters' fingerprint) and truncated to self_lsn. Part 1: vote_reply_dispatch now records the granting voter's (lsn,tag,grant) into ctx->votes[] via a record-only ha_record_vote_reply seam (no double-promotion; raft_on_vote_reply stays the sole production promotion driver) — so safe-commit reflects the true voted majority. Part 2: the candidate/voter advertise the real DURABLE (fsync'd) tip; persist_wal _write_replicated advances durable_lsn after its fail-loud inline fdatasync. Reviewer-verified SAFE (advertises only durable positions; safe-commit bounded by the durable majority, preserving more committed entries, never marking a non-majority-durable LSN safe). 177 unit tests; new test_ha_vote_gate + election tests green. PARTIAL: does NOT yet make the live clean-failover pass. A deeper slice of bug-828/795 remains — a catch-up'd standby still under-advertises its durable position in the live run (the documented architectural catch-up/durability gap), so a job-less node can still win and truncate. Tracked for a dedicated effort.
This commit is contained in:
parent
14c41cb298
commit
91b9a445f0
6 changed files with 313 additions and 20 deletions
|
|
@ -933,6 +933,25 @@ int persist_wal_write_replicated(persist_t* p, uint64_t lsn, uint32_t type,
|
|||
return -EIO;
|
||||
}
|
||||
|
||||
/* bug-828 secondary: the entry is now fdatasync'd durable, so advance
|
||||
* durable_lsn to the synced tip immediately (mirror persist_flush). The
|
||||
* 10ms cadence flusher would otherwise advance it lazily, leaving this
|
||||
* standby's ADVERTISED durable position (persist_durable_floor →
|
||||
* RequestVoteReply.peerLastLogLsn) lagging its own synced tip during the
|
||||
* vote window. A standby that has durably persisted the committed prefix
|
||||
* must advertise it at once so a clean failover's safe-commit-from-votes
|
||||
* computation sees the true majority-held LSN. Monotonic max; preserves
|
||||
* durable_lsn <= current_lsn - 1 (tip read under this same p->lock, after
|
||||
* the current_lsn advance above). Reached ONLY past the fail-loud rc-gate
|
||||
* — never advances on an fdatasync error. */
|
||||
{
|
||||
uint64_t tip = (p->current_lsn > 0) ? p->current_lsn - 1 : 0;
|
||||
uint64_t dur = atomic_load_explicit(&p->durable_lsn,
|
||||
memory_order_acquire);
|
||||
if (tip > dur)
|
||||
atomic_store_explicit(&p->durable_lsn, tip, memory_order_release);
|
||||
}
|
||||
|
||||
/* Rotate segment when full (same threshold as the primary append). */
|
||||
if (p->seg_offset >= WAL_SEGMENT_SIZE_BYTES) {
|
||||
if (rotate_segment(p) != 0) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue