crafty_proto/join.rs
1//! Cluster join handshake wire types over `/cluster/join` (join-rpc, join-version-skew).
2
3use serde::{Deserialize, Serialize};
4
5use crate::{Membership, NodeId};
6
7/// A request from a new node asking to join the cluster.
8#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
9pub struct JoinRequest {
10 /// Wire/protocol version of the joining node (join-version-skew).
11 pub protocol_version: u32,
12 /// Desired node id, or `None` to have the leader assign the next free id.
13 #[serde(default)]
14 pub node_id: Option<NodeId>,
15 /// Address peers should use to reach the joining node.
16 pub advertise_addr: String,
17}
18
19/// The response to a [`JoinRequest`].
20#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
21pub enum JoinResponse {
22 /// Join accepted; membership change committed by the leader.
23 Accepted {
24 /// Current leader.
25 leader: NodeId,
26 /// Id assigned to this node (matches the request when one was given).
27 node_id: NodeId,
28 /// Resulting cluster membership.
29 membership: Membership,
30 },
31 /// Contacted node is not the leader; retry against `leader`.
32 Redirect {
33 /// Best-known current leader, if any.
34 leader: Option<NodeId>,
35 },
36 /// Join refused.
37 Rejected {
38 /// Why the join was refused.
39 reason: JoinRejection,
40 },
41}
42
43/// One node's advertised address, as gossiped in a [`PeerBook`].
44#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
45pub struct PeerEntry {
46 /// The node this address belongs to.
47 pub node: NodeId,
48 /// The address peers should dial to reach it (`host:port`).
49 pub addr: String,
50}
51
52/// A snapshot of a node's known peer addresses, served over `/cluster/peers`
53/// (discovery) so a newly joined node — and existing members — can learn how to
54/// reach every peer without static, cluster-wide address configuration. This is
55/// the address-plane counterpart to the Raft-replicated membership (which
56/// carries only [`NodeId`]s, not addresses).
57#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)]
58pub struct PeerBook {
59 /// Known `(node, addr)` pairs, ascending by id.
60 pub entries: Vec<PeerEntry>,
61}
62
63/// Reason a [`JoinRequest`] was rejected.
64#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
65pub enum JoinRejection {
66 /// Protocol version mismatch — hard reject (join-version-skew).
67 VersionSkew {
68 /// Version the cluster expects.
69 expected: u32,
70 /// Version the joiner offered.
71 got: u32,
72 },
73 /// The cluster is not currently accepting joins (`--allow-join` off).
74 JoinsDisabled,
75 /// A node with this id is already a member.
76 Duplicate,
77 /// Any other refusal, human-readable.
78 Other(String),
79}