1use 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 pub fn tick(&mut self, node: &str) {
21 self.version.tick(node);
22 }
23
24 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#[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}