Step 01 — Cluster and Replica
Goal: in ~30 minutes, build a single-replica Cluster::new(1) that
accepts Put / Del and returns a state machine you can inspect.
What to read first
CONCEPTS.md§ "Data model" and § "Propose / commit cycle".db-17-raft/CONCEPTS.mdfor the words log entry, commit index, quorum if they are not yet second nature.
Concrete tasks
- Define
OpKind,Op,LogEntry,Replica,Clusterin the language of your choice. Match the field layout fromsrc/rust/src/lib.rs. - Implement
Replica::last_idx,Replica::try_append,Replica::advance_commit_to. Note thatapply(state_machine, op)is the only place wherestate_machinemutates outside oftruncate_and_replay. - Implement
Cluster::new(n),quorum,propose. For now, treat every reachable follower as a successful append (no NACK path yet).
Definition of done
#![allow(unused)] fn main() { let mut c = Cluster::new(1); assert!(c.propose(Op::Put("a".into(), vec![1,2,3]))); assert_eq!(c.leader().state_machine.get("a"), Some(&vec![1,2,3])); }
equivalents pass in Go and C++. Run cargo test single_replica_put_commits
to confirm.
Common bugs at this stage
- Forgetting to bump
next_log_idxso two proposals get the same idx. - Applying
opbefore the entry is committed. - Iterating an unsorted
mapsomewhere (Go) — even at this stage, start the habit ofsort.Strings(keys)before any deterministic output.