dynomite/embed/snapshots.rs
1//! Owned point-in-time topology snapshots.
2//!
3//! Each type is `Clone` and free of internal locks so it can be
4//! held across an `await` without blocking the runtime.
5
6use crate::cluster::peer::{Peer, PeerEndpoint, PeerState};
7use crate::cluster::Datacenter;
8use crate::hashkit::DynToken;
9
10/// Owned snapshot of one peer in the cluster ring.
11///
12/// # Examples
13///
14/// ```
15/// use dynomite::embed::PeerSnapshot;
16/// use dynomite::cluster::peer::{Peer, PeerEndpoint, PeerState};
17/// use dynomite::hashkit::DynToken;
18/// let p = Peer::new(
19/// 0, PeerEndpoint::tcp("h".into(), 1), "r".into(), "d".into(),
20/// vec![DynToken::from_u32(0)], true, true, false,
21/// );
22/// let snap = PeerSnapshot::from(&p);
23/// assert_eq!(snap.idx, 0);
24/// ```
25#[derive(Clone, Debug, Eq, PartialEq)]
26pub struct PeerSnapshot {
27 /// Index of the peer in the pool's peer array.
28 pub idx: u32,
29 /// Hostname or IP.
30 pub host: String,
31 /// TCP port.
32 pub port: u16,
33 /// Datacenter name.
34 pub dc: String,
35 /// Rack name.
36 pub rack: String,
37 /// Lifecycle state.
38 pub state: PeerState,
39 /// Token list at snapshot time.
40 pub tokens: Vec<DynToken>,
41 /// True for the local node.
42 pub is_local: bool,
43}
44
45impl From<&Peer> for PeerSnapshot {
46 fn from(p: &Peer) -> Self {
47 Self {
48 idx: p.idx(),
49 host: p.endpoint().host().to_string(),
50 port: p.endpoint().port(),
51 dc: p.dc().to_string(),
52 rack: p.rack().to_string(),
53 state: p.state(),
54 tokens: p.tokens().to_vec(),
55 is_local: p.is_local(),
56 }
57 }
58}
59
60impl PeerSnapshot {
61 /// Convert back to a runtime [`Peer`] (used by tests and
62 /// by the embed-internal forwarder).
63 #[must_use]
64 pub fn to_peer(&self) -> Peer {
65 Peer::new(
66 self.idx,
67 PeerEndpoint::tcp(self.host.clone(), self.port),
68 self.rack.clone(),
69 self.dc.clone(),
70 self.tokens.clone(),
71 self.is_local,
72 true,
73 false,
74 )
75 }
76}
77
78/// Owned snapshot of one rack in a datacenter.
79#[derive(Clone, Debug, Eq, PartialEq)]
80pub struct RackSnapshot {
81 /// Rack name.
82 pub name: String,
83 /// Continuum size.
84 pub continuum_len: usize,
85}
86
87/// Owned snapshot of one datacenter and its racks.
88#[derive(Clone, Debug, Eq, PartialEq)]
89pub struct DatacenterSnapshot {
90 /// DC name.
91 pub name: String,
92 /// Racks in this DC.
93 pub racks: Vec<RackSnapshot>,
94}
95
96impl From<&Datacenter> for DatacenterSnapshot {
97 fn from(dc: &Datacenter) -> Self {
98 Self {
99 name: dc.name().to_string(),
100 racks: dc
101 .racks()
102 .iter()
103 .map(|r| RackSnapshot {
104 name: r.name().to_string(),
105 continuum_len: r.continuums().len(),
106 })
107 .collect(),
108 }
109 }
110}
111
112/// Owned snapshot of the token ring.
113///
114/// Each entry is a `(token, owner_peer_idx)` pair.
115#[derive(Clone, Debug, Default, Eq, PartialEq)]
116pub struct RingSnapshot {
117 /// Token-to-owner pairs in token order.
118 pub entries: Vec<(DynToken, u32)>,
119 /// Monotonic generation counter.
120 pub generation: u64,
121}