Skip to main content

dactor_mock/
network.rs

1use std::sync::Mutex;
2
3use dactor::node::NodeId;
4
5/// Simulated network between mock nodes.
6/// Routes messages and can inject faults (partitions, latency, drops).
7pub struct MockNetwork {
8    partitions: Mutex<Vec<(NodeId, NodeId)>>,
9    delivered: Mutex<u64>,
10    dropped: Mutex<u64>,
11}
12
13impl MockNetwork {
14    pub fn new() -> Self {
15        Self {
16            partitions: Mutex::new(Vec::new()),
17            delivered: Mutex::new(0),
18            dropped: Mutex::new(0),
19        }
20    }
21
22    /// Partition two nodes — block all messages between them.
23    pub fn partition(&self, a: &NodeId, b: &NodeId) {
24        let mut parts = self.partitions.lock().unwrap();
25        parts.push((a.clone(), b.clone()));
26    }
27
28    /// Remove a partition between two nodes, restoring connectivity.
29    pub fn remove_partition(&self, a: &NodeId, b: &NodeId) {
30        let mut parts = self.partitions.lock().unwrap();
31        parts.retain(|(x, y)| !((x == a && y == b) || (x == b && y == a)));
32    }
33
34    /// Check if two nodes are partitioned.
35    pub fn is_partitioned(&self, a: &NodeId, b: &NodeId) -> bool {
36        let parts = self.partitions.lock().unwrap();
37        parts
38            .iter()
39            .any(|(x, y)| (x == a && y == b) || (x == b && y == a))
40    }
41
42    /// Total messages delivered.
43    pub fn delivered_count(&self) -> u64 {
44        *self.delivered.lock().unwrap()
45    }
46
47    /// Total messages dropped (due to partitions, etc).
48    pub fn dropped_count(&self) -> u64 {
49        *self.dropped.lock().unwrap()
50    }
51
52    /// Check if a message from src to dst should be delivered.
53    /// Returns false if nodes are partitioned.
54    pub fn can_deliver(&self, src: &NodeId, dst: &NodeId) -> bool {
55        if src == dst {
56            return true;
57        }
58        !self.is_partitioned(src, dst)
59    }
60
61    /// Record a successful delivery.
62    pub fn record_delivered(&self) {
63        *self.delivered.lock().unwrap() += 1;
64    }
65
66    /// Record a dropped message.
67    pub fn record_dropped(&self) {
68        *self.dropped.lock().unwrap() += 1;
69    }
70}
71
72impl Default for MockNetwork {
73    fn default() -> Self {
74        Self::new()
75    }
76}