moonpool_sim/runner/
topology.rs

1//! Workload topology configuration.
2//!
3//! This module provides types for configuring workload topology and
4//! creating topology information for individual workloads.
5
6use crate::chaos::StateRegistry;
7
8/// Topology information provided to workloads to understand the simulation network.
9#[derive(Debug, Clone)]
10pub struct WorkloadTopology {
11    /// The IP address assigned to this workload
12    pub my_ip: String,
13    /// The IP addresses of all other peers in the simulation
14    pub peer_ips: Vec<String>,
15    /// The names of all other peers in the simulation (parallel to peer_ips)
16    pub peer_names: Vec<String>,
17    /// Shutdown signal that gets triggered when the first workload exits with Ok
18    pub shutdown_signal: tokio_util::sync::CancellationToken,
19    /// State registry for cross-workload invariant checking
20    pub state_registry: StateRegistry,
21}
22
23impl WorkloadTopology {
24    /// Find the IP address of a peer by its workload name
25    pub fn get_peer_by_name(&self, name: &str) -> Option<String> {
26        self.peer_names
27            .iter()
28            .position(|peer_name| peer_name == name)
29            .map(|index| self.peer_ips[index].clone())
30    }
31
32    /// Get all peers with a name prefix (useful for finding multiple clients, servers, etc.)
33    pub fn get_peers_with_prefix(&self, prefix: &str) -> Vec<(String, String)> {
34        self.peer_names
35            .iter()
36            .zip(self.peer_ips.iter())
37            .filter(|(name, _)| name.starts_with(prefix))
38            .map(|(name, ip)| (name.clone(), ip.clone()))
39            .collect()
40    }
41}
42
43/// A registered workload that can be executed during simulation.
44pub struct Workload {
45    pub(crate) name: String,
46    pub(crate) ip_address: String,
47    pub(crate) workload: super::builder::WorkloadFn,
48}
49
50impl std::fmt::Debug for Workload {
51    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
52        f.debug_struct("Workload")
53            .field("name", &self.name)
54            .field("ip_address", &self.ip_address)
55            .field("workload", &"<closure>")
56            .finish()
57    }
58}
59
60/// Factory for creating workload topology configurations.
61pub(crate) struct TopologyFactory;
62
63impl TopologyFactory {
64    /// Create topology for a specific workload within a set of all workloads.
65    pub(crate) fn create_topology(
66        workload_ip: &str,
67        all_workloads: &[Workload],
68        shutdown_signal: tokio_util::sync::CancellationToken,
69        state_registry: StateRegistry,
70    ) -> WorkloadTopology {
71        let peer_ips = all_workloads
72            .iter()
73            .filter(|w| w.ip_address != workload_ip)
74            .map(|w| w.ip_address.clone())
75            .collect();
76
77        let peer_names = all_workloads
78            .iter()
79            .filter(|w| w.ip_address != workload_ip)
80            .map(|w| w.name.clone())
81            .collect();
82
83        WorkloadTopology {
84            my_ip: workload_ip.to_string(),
85            peer_ips,
86            peer_names,
87            shutdown_signal,
88            state_registry,
89        }
90    }
91}