openraft 0.9.23

Advanced Raft consensus
Documentation
# Formation of Clusters

When a `Raft` node is created by [`Raft::new()`], it enters the `Learner` state.

In order to establish a cluster, the application invokes [`Raft::initialize(membership)`][`Raft::initialize()`].


## `Raft::initialize()`

This method will:

- Add a membership log at index 0 with the log id `(leader_id=LeaderId::default(), index=0)`.
  The membership will be immediately effective.

- Transition to the `Candidate` state and initiate voting to become the leader.

- The leader will commit an blank log to commit all previous logs.

### Errors and Failures

- If this method is called on a node that has already been initialized, it will simply return an error and remain safe,
  i.e., if `last_log_id` on this node is not `None`, or `vote` on this node is not `(0,0)`.

- If this method is called on more than one node simultaneously:

    - with the same `membership`, it is safe,
      as the voting protocol ensures consistency.

    - with different `membership`, it is **ILLEGAL** and will lead to an undefined
      state, also known as the **split-brain** state.

### Preconditions for Initialization

The legal initialization conditions are as follows:

The initial membership log with log id `(leader_id=LeaderId::default(), index=0)` will be appended to a node without consensus.
This must not violate the commit condition:

1. Log id `(leader_id=LeaderId::default(), index=0)` must not exceed any committed log id.
   If `leader_id` is not the smallest value, i.e., `(term=0, node_id=0)`, it may be greater than some
   committed log id. This is why the first log must be the smallest: `((term=0, node_id=0), 0)`.

2. A node should not append a log that is smaller than its `vote`.
   Otherwise, it is effectively altering the **history** seen by other nodes.
   This may (but not necessarily) disrupt consensus, depending on the protocol.
   For example, if the cluster has been running a fast-paxos-like protocol, appending a smaller log than `vote` is illegal.
   By prohibiting the appending of a smaller log than `vote`, it will always be safe.

For these two reasons, appending the first log is only allowed if:
`vote==(0,0)`. This is why the initial value of `vote` must be `(0,0)`.

[`Raft::initialize()`]: `crate::Raft::initialize`
[`Raft::new()`]:        `crate::Raft::new`