Skip to main content

moonpool_sim/chaos/
fault_events.rs

1//! Simulator-emitted fault events for the event timeline.
2//!
3//! When faults are injected (network partitions, process reboots, storage corruption, etc.),
4//! the simulator automatically emits [`SimFaultEvent`]s to the [`SIM_FAULT_TIMELINE`] timeline.
5//! Invariants can read these to correlate application behavior with infrastructure faults.
6//!
7//! # Usage
8//!
9//! ```ignore
10//! use moonpool_sim::{Invariant, StateHandle, SimFaultEvent, SIM_FAULT_TIMELINE};
11//!
12//! fn check(state: &StateHandle, _sim_time_ms: u64) {
13//!     if let Some(faults) = state.timeline::<SimFaultEvent>(SIM_FAULT_TIMELINE) {
14//!         for entry in faults.all().iter() {
15//!             match &entry.event {
16//!                 SimFaultEvent::ProcessForceKill { ip } => { /* ... */ }
17//!                 _ => {}
18//!             }
19//!         }
20//!     }
21//! }
22//! ```
23
24/// Well-known timeline key for simulator-emitted fault events.
25pub const SIM_FAULT_TIMELINE: &str = "sim:faults";
26
27/// Fault events automatically emitted by the simulator.
28///
29/// Read via `state.timeline::<SimFaultEvent>(SIM_FAULT_TIMELINE)` in invariants.
30#[derive(Debug, Clone)]
31pub enum SimFaultEvent {
32    // -- Process lifecycle --
33    /// Process graceful shutdown initiated.
34    ProcessGracefulShutdown {
35        /// IP address of the process.
36        ip: String,
37        /// Grace period before force-kill, in milliseconds.
38        grace_period_ms: u64,
39    },
40    /// Process force-killed.
41    ProcessForceKill {
42        /// IP address of the process.
43        ip: String,
44    },
45    /// Process restarted after recovery delay.
46    ProcessRestart {
47        /// IP address of the process.
48        ip: String,
49    },
50
51    // -- Network --
52    /// Bidirectional network partition created between two IPs.
53    PartitionCreated {
54        /// Source IP.
55        from: String,
56        /// Destination IP.
57        to: String,
58    },
59    /// Network partition healed between two IPs.
60    PartitionHealed {
61        /// Source IP.
62        from: String,
63        /// Destination IP.
64        to: String,
65    },
66    /// Connection temporarily cut.
67    ConnectionCut {
68        /// The connection that was cut.
69        connection_id: u64,
70        /// Duration of the cut in milliseconds.
71        duration_ms: u64,
72    },
73    /// Temporarily cut connection restored.
74    CutRestored {
75        /// The connection that was restored.
76        connection_id: u64,
77    },
78    /// Half-open connection error triggered.
79    HalfOpenError {
80        /// The connection now returning errors.
81        connection_id: u64,
82    },
83    /// Send partition created (blocks outgoing from an IP).
84    SendPartitionCreated {
85        /// The partitioned IP.
86        ip: String,
87    },
88    /// Receive partition created (blocks incoming to an IP).
89    RecvPartitionCreated {
90        /// The partitioned IP.
91        ip: String,
92    },
93    /// Connection randomly closed by chaos.
94    RandomClose {
95        /// The connection that was closed.
96        connection_id: u64,
97    },
98    /// Peer crash simulated (half-open connection created).
99    PeerCrash {
100        /// The connection now in half-open state.
101        connection_id: u64,
102    },
103    /// Bit flip corruption injected during data delivery.
104    BitFlip {
105        /// The connection carrying corrupted data.
106        connection_id: u64,
107        /// Number of bits flipped.
108        flip_count: usize,
109    },
110
111    // -- Storage --
112    /// Read fault injected (sector marked as faulted).
113    StorageReadFault {
114        /// IP of the process owning the file.
115        ip: String,
116        /// File identifier.
117        file_id: u64,
118    },
119    /// Write fault injected (phantom, misdirected, or corruption).
120    StorageWriteFault {
121        /// IP of the process owning the file.
122        ip: String,
123        /// File identifier.
124        file_id: u64,
125        /// Kind of write fault: "phantom", "misdirected", or "corruption".
126        kind: String,
127    },
128    /// Sync failure injected.
129    StorageSyncFault {
130        /// IP of the process owning the file.
131        ip: String,
132        /// File identifier.
133        file_id: u64,
134    },
135    /// Storage crash simulated for a process.
136    StorageCrash {
137        /// IP of the crashed process.
138        ip: String,
139    },
140    /// All storage wiped for a process (CrashAndWipe reboot).
141    StorageWipe {
142        /// IP of the wiped process.
143        ip: String,
144    },
145}