Skip to main content

atomr_cluster/
gossip.rs

1//! Gossip envelope. akka.net: `Cluster/Gossip.cs`, `GossipOverview.cs`.
2
3use serde::{Deserialize, Serialize};
4
5use crate::membership::MembershipState;
6use crate::vector_clock::VectorClock;
7
8#[derive(Debug, Clone, Default, Serialize, Deserialize)]
9pub struct Gossip {
10    pub version: VectorClock,
11    pub state: MembershipState,
12}
13
14impl Gossip {
15    pub fn new() -> Self {
16        Self::default()
17    }
18
19    /// Increment our local clock entry for `node`.
20    pub fn tick(&mut self, node: &str) {
21        self.version.tick(node);
22    }
23
24    /// Merge with another gossip, taking vector-clock max and union of members.
25    pub fn merge(&self, other: &Self) -> Self {
26        let mut merged = Self { version: self.version.merge(&other.version), ..Self::default() };
27        for m in self.state.members.iter().chain(other.state.members.iter()) {
28            merged.state.add_or_update(m.clone());
29        }
30        for ((a, b), st) in
31            self.state.reachability.records.iter().chain(other.state.reachability.records.iter())
32        {
33            merged.state.reachability.records.insert((a.clone(), b.clone()), *st);
34        }
35        merged
36    }
37}
38
39/// Snapshot of seen-by + unreachable info. akka.net: `GossipOverview.cs`.
40#[derive(Debug, Clone, Default, Serialize, Deserialize)]
41pub struct GossipOverview {
42    pub seen_by: Vec<String>,
43    pub reachability: crate::reachability::Reachability,
44}
45
46#[cfg(test)]
47mod tests {
48    use super::*;
49    use crate::member::Member;
50    use atomr_core::actor::Address;
51
52    #[test]
53    fn merge_is_commutative_for_members() {
54        let mut a = Gossip::new();
55        a.tick("A");
56        a.state.add_or_update(Member::new(Address::local("A"), vec![]));
57        let mut b = Gossip::new();
58        b.tick("B");
59        b.state.add_or_update(Member::new(Address::local("B"), vec![]));
60        let ab = a.merge(&b);
61        let ba = b.merge(&a);
62        assert_eq!(ab.state.member_count(), 2);
63        assert_eq!(ab.state.member_count(), ba.state.member_count());
64    }
65}