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
- Leader check. Snapshot the group-0 leader id and clone the
routing table under a single
MultiRaftlock. If another node is the leader, return a redirect response with that node’s address. - Validate address. Parse
req.listen_addr. On failure, return an error response. - 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.
- Register transport peer. Add the new peer address to the local transport so the leader can immediately send AppendEntries to the learner-to-be.
- Admit into topology. Under a short
topology.write()guard, callbootstrap::handle_join_request— the only side effect is inserting the newNodeInfo. 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. - Propose AddLearner on every group. For each Raft group, take
the
MultiRaftlock, proposeConfChange::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 withNotLeader— 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.) - Wait for each conf-change to commit. Poll
commit_index_foron 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. - Persist topology + routing to catalog (when a catalog is attached). Order matters: Raft log → catalog → response.
- Broadcast TopologyUpdate to every currently-active peer so followers learn the new node’s address. Fire-and-forget.
- 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.