Skip to main content

Module join

Module join 

Source
Expand description

Server-side JoinRequest orchestration.

This is the async flow invoked by the RaftRpc::JoinRequest arm in super::handle_rpc. It turns a remote node’s desire to join the cluster into a series of durable Raft conf-changes and returns a JoinResponse containing everything the joining node needs to reconstruct its local MultiRaft in the Learner role.

§Flow

  1. Leader check. Snapshot the group-0 leader id and clone the routing table under a single MultiRaft lock. If another node is the leader, return a redirect response with that node’s address.
  2. Validate address. Parse req.listen_addr. On failure, return an error response.
  3. Idempotency / collision check. If the node id is already in topology with the same address and is Active, rebuild and return the current response without any further Raft activity. If the node id exists with a different address, reject.
  4. Register transport peer. Add the new peer address to the local transport so the leader can immediately send AppendEntries to the learner-to-be.
  5. Admit into topology. Under a short topology.write() guard, call bootstrap::handle_join_request — the only side effect is inserting the new NodeInfo. The routing-table clone we took in step 1 is intentionally not reused for the final response; a fresh clone is taken after step 6 so the response reflects the post-AddLearner routing state.
  6. Propose AddLearner on every group. For each Raft group, take the MultiRaft lock, propose ConfChange::AddLearner(new_node_id), and record the resulting log index. Drop the lock between groups. If this node is not the leader of a particular group the propose will fail with NotLeader — we surface that as a failure response. (For the 3-node bootstrap case in the integration test the bootstrap seed leads every group, so this path is exercised end-to-end.)
  7. Wait for each conf-change to commit. Poll commit_index_for on each group every 20 ms with a 5-second deadline. A single-voter group (the bootstrap seed before any voters have been added) commits instantly. Multi-voter groups wait for quorum. On timeout, return an error response — the joining node will retry the whole flow.
  8. Persist topology + routing to catalog (when a catalog is attached). Order matters: Raft log → catalog → response.
  9. Broadcast TopologyUpdate to every currently-active peer so followers learn the new node’s address. Fire-and-forget.
  10. Build and return JoinResponse with the updated routing (which now includes the new node as a learner on every group).

The Raft-level promotion from learner to voter happens asynchronously in the tick loop (super::tick::promote_ready_learners) once the learner’s match_index catches up. That avoids blocking the join handler on replication progress while still completing the two-phase single-server add.