Commit graph

86 commits

Author SHA1 Message Date
7dc657b1bd feat(ha-repl-hardening): populate stateReport in standby heartbeat reply (task 2.3)
OPCode_nop handler now sends stateReport {applied_lsn, config_tag}
instead of nodata. Function in ha.c for unit-test linkability.
Two tests: warm state and zero-state fresh standby (Req 1.4).
2026-06-04 16:08:11 +00:00
6bbcff62ca feat(ha-repl-hardening): add batch WAL catch-up on standby side (task 2.2)
Extend ha_apply_wal_catchup_entry with batch branch:
- Check n_entries > 0, iterate entries[] list in order
- Apply each via apply_wal_entry(); skip NULL/errors without crash
- Advance applied_lsn once after full batch (not per-entry)
- n_entries == 0 falls through to task 2.1 single-entry path
4 new unit tests covering full batch, partial batch, error skip, fallback
2026-06-04 15:38:20 +00:00
647b88ce57 feat(ha-repl-hardening): wire OPCode_walCatchupEntry standby handler (task 2.1)
Replace stub with ha_apply_wal_catchup_entry() calling apply_wal_entry().
CAS-advance applied_lsn on success; log ERROR and skip on failure.
Standby stays in CTRL_STANDBY throughout. 3 new unit tests.
2026-06-04 15:05:52 +00:00
e3ca775f0d feat(ha-repl-hardening): add per-standby convergence tracking arrays (task 1.4)
Add standby_reported_tag/lsn/converged arrays to ha_state_t, sized
MAX_HA_CANDIDATES. Zero-init via existing memset in ha_init().
Unit test verifies zero-init and writability.
2026-06-04 14:14:23 +00:00
0121bc0683 feat(ha-repl-hardening): add snapshot chunk fields to capnp schema (task 1.3)
Extend SnapshotTransfer struct from 2 to 6 fields:
- snapshotLsn (existing), chunkIndex, chunkOffset, totalSize,
  isLast, payload (existing)
No resumption fields per restart-on-reconnect policy.
2026-06-04 13:55:45 +00:00
51907ebfbc feat(ha-repl-hardening): add batch entries list to WalCatchupEntry schema (task 1.2)
Add self-referential entries @3 :List(WalCatchupEntry) field with
$C.maplistcount("n_entries"). Single-entry path unaffected — n_entries
defaults to 0, entries to NULL when not using batch mode.
2026-06-04 13:46:04 +00:00
9a977b3a43 feat(ha-repl-hardening): add StateReport to RequestReply capnp schema (task 1.1)
Add StateReport struct {appliedLsn, configTag} as stateReportMsg @15
variant in RequestReply.data union. Standby populates this in heartbeat
replies so the primary can track per-standby convergence.

capnpc-c 1.0.1 has a bug with inline :group inside codecgen unions;
workaround uses named outer struct (wire-equivalent). typemap.h
extended with state_report_t and union member for C codec access.
2026-06-04 13:34:11 +00:00
e31673dd88 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
2026-06-04 13:04:16 +00:00
15bd291bdd docs(ha-repl-hardening): add spec with reviewed design and approved tasks
- requirements.md: 7 requirements covering heartbeat state reporting,
  majority convergence tracking, WAL catch-up, snapshot transfer, batch
  WAL, COMMITTING gate, and observability
- design.md: unified heartbeat-driven replication design; reviewed and
  fixed three issues (snapshot resumption→restart-on-reconnect, WAL
  streaming non-blocking contract, applied_lsn durability)
- tasks.md: 21 sub-tasks across 6 groups; sanity reviewed and fixed
  (removed resumption language from tasks 3.5/6.4, added Req 3.4
  coverage, fixed 2.1/2.2 dependency, log coverage trace in 5.4)
- spec.json: design and tasks approved, ready for implementation
2026-06-04 12:58:39 +00:00
374f3bfd0e chore(ha-config-bootstrap): gap analysis audit + fix parent task headers
- Gap analysis: all 10 requirements verified implemented in live codebase
  (ha.c, ha.h, config_repl.c, request.c).
- Fix parent group headers (1-10) to [x] since all leaf subtasks complete.
- Mark task 11.5 complete: /xce-build controller passes 1/1 tests, ASAN clean.
- Remaining: integration tests 11.1-11.4 (manual cluster tests, documented
  in manual-tests.md).
2026-06-03 06:04:58 +00:00
e56b2064de test(ha-heartbeat-liveness): SIGSTOP/SIGCONT tolerance integration test (task 4.5)
Add src/tools/test-heartbeat-tolerance.sh: automated bash script that
deploys a 3-node cluster and runs two SIGSTOP/SIGCONT scenarios:

  Scenario A (1 × heartbeat_interval_ms pause): verifies no RDHUP fires on
  standbys — liveness_poll_fn must not trigger failover for a short silence
  within the tolerance window (Req 2.2).

  Scenario B (heartbeat_timeout_ms + 500ms pause): verifies exactly one RDHUP
  fires on each standby — the activity-based poll fires after sustained silence
  and does not loop (Req 2.3, Req 5.4).

Add .kiro/specs/ha-heartbeat-liveness/manual-tests.md: step-by-step manual
procedure, expected log patterns, and results template for both scenarios.

Mark task 4.5 complete in tasks.md.
2026-06-03 04:18:56 +00:00
529552c127 fix(ha-heartbeat-liveness): start primary heartbeat in COMMITTING phase (task 4.3)
Call ha_start_primary_heartbeat in raft_cb_become_leader when entering
CTRL_PRIMARY_COMMITTING so standbys receive NOPs during the committing
window. Fixes 60s stability: 0 false RDHUP events on standbys.
2026-06-01 15:56:36 +00:00
aceadf0357 chore(ha-heartbeat-liveness): mark unit test tasks 4.1-4.2 complete
All required unit test cases already implemented in prior tasks.
2026-06-01 15:43:29 +00:00
12216f1165 feat(ha-heartbeat-liveness): verify ctrlhello integration and RDHUP cancel (task 3.2)
Verification task: confirmed config_repl.c handle_ctrlhello calls both
ha_on_heartbeat_received and ha_arm_heartbeat_timeout_vtask (delaymgr poll).
Confirmed ha_on_primary_ctrl_fd_rdhup leads with ha_disarm (Req 5.4).
No pthread_create in heartbeat arm path (Req 1.6). Add thread-count test.
2026-06-01 15:37:35 +00:00
d937c1c1bb feat(ha-heartbeat-liveness): role-based liveness reset in opcode dispatch (task 3.1)
Replace fd-based guard in OPCode_nop with role==CTRL_STANDBY check.
Add ha_on_heartbeat_received call to OPCode_hello ctrlhello path when standby.
Satisfies Req 1.3 (any message resets deadline) and Req 4.1 (ctrlhello counts).
3 new dispatch guard tests added to test_ha_liveness.c.
2026-06-01 15:31:15 +00:00
622302a55c feat(ha-heartbeat-liveness): idle-triggered primary NOP per standby (task 2.2)
Extend primary_heartbeat_fn to read last_push_time per standby and send NOP
only when elapsed >= heartbeat_interval_s. on_standby_connected writes
last_push_time before ctrlhello send. Remove workaround xce_nop_req at end
of on_standby_connected. Add ha_nop_req_hook XCE_TESTING seam. 3 new tests.
2026-06-01 15:05:41 +00:00
738859fb4e feat(ha-heartbeat-liveness): replace hb_timeout_thread with liveness_poll_fn (task 2.1)
Remove hb_vtask_t, hb_timeout_thread, s_hb_vtask from ha.c. Replace with
liveness_poll_ctx_t + delaymgr liveness_poll_fn: checks cancelled flag and
role==CTRL_STANDBY before acting; re-arms at heartbeat_interval_ms/2.
ha_on_primary_ctrl_fd_rdhup calls ha_disarm_heartbeat_timeout_vtask first
to prevent duplicate failover (Req 5.4). ha_on_heartbeat_received writes
last_activity via clock_gettime. Add test_ha_liveness.c with 7 unit tests.
2026-06-01 14:34:14 +00:00
9f9a6b3c0f feat(ha-heartbeat-liveness): add validate_heartbeat_config startup check (task 1.2)
Enforce heartbeat_timeout_ms >= 2 * heartbeat_interval_ms at startup.
validate_heartbeat_config() in startup_validation.c returns -EINVAL with
error message on violation; wired in cluster_init_phase1 before ha_init().
4 unit tests added to test_ha_startup.c.
2026-06-01 12:26:29 +00:00
bcb45e59d2 feat(ha-heartbeat-liveness): add last_activity and last_push_time state fields (task 1.1)
Add time_t last_activity to ha_state_t for standby liveness timestamp tracking.
Add time_t last_push_time to standby_ep_ctx_t for primary idle NOP suppression.
Zero-initialize last_activity in ha_init(); last_push_time zeroed by calloc.
Add test_ha_init_last_activity_is_zero to test_ha_startup.c.
2026-06-01 11:59:16 +00:00
e85100d761 test(ha-peer-connection-reuse): complete tasks 7.1, 7.2, 7.3 — all validation done
Task 7.1 (unit tests) was already complete with 8 tests in
test_ha_connection_reuse.c. Added two new tests:

Task 7.2 — test_follower_passive_no_outbound_connect (Req 2.1, 2.4):
  Verifies raft_cb_become_follower sets role=CTRL_STANDBY and nulls all
  votes[i].ep. The old fetch_config_from_primary path is gone; standbys
  never initiate outbound connects after election loss.

Task 7.3 — test_promoted_ep_repl_ack_promotes_to_primary (Req 5.2, 5.4):
  Injects two OPCode_replCatchUpDone packets via peer_ctrl_msg_handler in
  CTRL_PRIMARY_COMMITTING with n_peers=4 (5-node cluster, quorum=2 ACKs).
  Verifies repl_ack_count reaches 2 and role transitions to CTRL_PRIMARY.
  Added vote_ep_ctx_set_cluster_for_test() seam so vctx->c is non-NULL
  when ha_repl_ack_received fires ha_promote_to_primary.

All 62 controller tests pass; ASAN clean.
spec: .kiro/specs/ha-peer-connection-reuse/tasks.md all tasks [x]
2026-06-01 07:53:02 +00:00
937605ec60 feat(raft-library): tasks 6.4 + 7 complete — all ASAN-clean, hooks verified, spec closed 2026-05-31 09:25:20 +00:00
fd9933c9d0 feat(raft-library): task 6.3 — delegate election dispatch to raft_* API in ha.c + cluster.c 2026-05-31 08:43:01 +00:00
8f0d2d55c3 feat(raft-library): task 6.2 — real raft callbacks in ha.c; fix double-free + dead stubs 2026-05-31 07:53:00 +00:00
b77525deb0 feat(raft-library): task 6.1 — raft_state_t field in ha_state_t, raft_init with no-op stubs 2026-05-31 07:20:15 +00:00
6bdf7edacf feat(raft-library): task 5.4 — Groups F+G, 6 test cases (RDHUP failover + split-brain) 2026-05-31 07:05:45 +00:00
5c677bc52d feat(raft-library): task 5.3 — Groups D+E 7 test cases; fix Req 6.3 on_cancel_timeout in decided path 2026-05-31 06:58:02 +00:00
0aa4c84bfe feat(raft-library): task 5.2 — protocol Groups C+H, 11 test cases (eligible policy + persist) 2026-05-31 06:34:33 +00:00
389047194f feat(raft-library): task 5.1 — protocol Groups A+B, 10 test cases (election + voted_for) 2026-05-31 06:26:52 +00:00
c1b07392df feat(raft-library): task 4.2 — sim deliver/partition/timeout/start-all; 4 tests 2026-05-31 06:20:35 +00:00
d2e2c1ef8a feat(raft-library): task 4.1 — sim data structures, raft_sim_init, dump_log; 2 tests 2026-05-31 06:11:34 +00:00
85a7e325a8 feat(raft-library): task 3.5 — election timeout, leader-lost, check-and-start; 6 tests 2026-05-31 06:02:29 +00:00
f81054930f feat(raft-library): task 3.4 — raft_on_vote_reply quorum tracking; 6 tests + review fixes 2026-05-31 05:56:34 +00:00
e0bcb35554 feat(raft-library): task 3.3 — raft_on_vote_request 6-step decision; 10 tests 2026-05-31 05:44:34 +00:00
4955fa3805 feat(raft-library): task 3.2 — raft_start_election with single-node shortcircuit; 4 tests 2026-05-31 05:30:00 +00:00
1aa7db4583 feat(raft-library): task 3.1 — raft_init validation, state init, raft_snapshot; 12 tests 2026-05-31 05:18:42 +00:00
d109155a21 feat(raft-library): task 2.2 — raft_callbacks_t, raft_config_t, public API signatures 2026-05-31 05:03:04 +00:00
66c9810823 feat(raft-library): task 2.1 — raft_role_t, raft_state_t, raft_snapshot_t in raft.h 2026-05-31 04:56:49 +00:00
7f7de013b9 feat(raft-library): task 1.1 — build scaffold (raft/ files + meson wiring) 2026-05-31 04:51:42 +00:00
e875cae7ad chore(election-iomgr-refactor): mark tasks 6.1 and 6.2 complete in tasks.md 2026-05-30 13:46:17 +00:00
27ea14cd9a feat(election-iomgr-refactor): remove old blocking election code (am_i_primary_quorum, vote_request_thread, bootstrap_config_if_needed) — task 5.3 2026-05-30 13:04:19 +00:00
2e5681387a feat(election-iomgr-refactor): restructure myapp_run to fully non-blocking async startup — task 5.1 2026-05-30 12:26:56 +00:00
f4a6726f1b feat(election-iomgr-refactor): COMMITTING path in ha_elect_evaluate_and_signal + committing/election timeout watchdogs — tasks 4.1, 4.3, 4.4 2026-05-30 11:37:12 +00:00
e6135ea828 feat(election-iomgr-refactor): extend ha_dispatch_gate for CTRL_PRIMARY_COMMITTING — task 3.1 2026-05-30 10:28:36 +00:00
b8e6404fe2 docs(ha-bootstrap): fix config tag length: 12 hex chars (6 bytes), not 16 2026-05-29 13:27:01 +00:00
96df7285da docs(ha-config-bootstrap): add path verification warning — config must be in workdir/myname/conf/ 2026-05-29 11:11:29 +00:00
25c71adffb docs(ha-config-bootstrap): Test 11.1 now covers config replication verification 2026-05-29 11:02:45 +00:00
bc2aaff089 docs(ha-config-bootstrap): only primary needs initial config — standbys get it via replication 2026-05-29 10:59:51 +00:00
f465af0c0c docs(ha-config-bootstrap): add initial cluster config installation steps 2026-05-29 10:57:09 +00:00
bb4e23663a docs(ha-config-bootstrap): update manual tests to 3-node cluster (odd peer count design requirement) 2026-05-29 10:41:11 +00:00
abdb195c8e docs(ha-config-bootstrap): add TLS cert setup instructions to manual test guide 2026-05-29 10:34:41 +00:00