Skip to main content

citadel_sync/
node_id.rs

1/// Unique node identifier for replication.
2///
3/// Each database instance generates a random `NodeId` on creation.
4/// Used as a deterministic tiebreaker in LWW conflict resolution
5/// when two entries have identical HLC timestamps.
6///
7/// Serialized as 8 bytes big-endian for consistent byte ordering.
8#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
9pub struct NodeId(u64);
10
11impl NodeId {
12    pub fn random() -> Self {
13        use rand::Rng;
14        Self(rand::thread_rng().gen())
15    }
16
17    #[inline]
18    pub fn from_u64(v: u64) -> Self {
19        Self(v)
20    }
21
22    #[inline]
23    pub fn as_u64(&self) -> u64 {
24        self.0
25    }
26
27    #[inline]
28    pub fn to_bytes(&self) -> [u8; 8] {
29        self.0.to_be_bytes()
30    }
31
32    #[inline]
33    pub fn from_bytes(b: [u8; 8]) -> Self {
34        Self(u64::from_be_bytes(b))
35    }
36}
37
38impl std::fmt::Debug for NodeId {
39    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
40        write!(f, "NodeId({:016x})", self.0)
41    }
42}
43
44impl std::fmt::Display for NodeId {
45    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
46        write!(f, "{:016x}", self.0)
47    }
48}
49
50#[cfg(test)]
51#[path = "node_id_tests.rs"]
52mod tests;