pub struct SimulationBuilder { /* private fields */ }Expand description
Builder pattern for configuring and running simulation experiments.
Implementations§
Source§impl SimulationBuilder
impl SimulationBuilder
Sourcepub fn workload(self, w: impl Workload) -> Self
pub fn workload(self, w: impl Workload) -> Self
Add a single workload instance to the simulation.
The instance is reused across iterations (the run() method is called
each iteration on the same struct). Gets client_id = 0, client_count = 1.
Sourcepub fn workload_with_client_id(
self,
client_id: ClientId,
w: impl Workload,
) -> Self
pub fn workload_with_client_id( self, client_id: ClientId, w: impl Workload, ) -> Self
Add a single workload instance with a custom client ID strategy.
Like workload(), but the resolved client ID is
available via SimContext::client_id().
Sourcepub fn processes(
self,
count: impl Into<ProcessCount>,
factory: impl Fn() -> Box<dyn Process> + 'static,
) -> Self
pub fn processes( self, count: impl Into<ProcessCount>, factory: impl Fn() -> Box<dyn Process> + 'static, ) -> Self
Add server processes to the simulation.
Processes represent the system under test — they can be killed and restarted (rebooted). A fresh instance is created from the factory on every boot.
The count parameter accepts either a fixed usize or a
RangeInclusive<usize> for seeded random count per iteration.
Only one .processes() call is supported per builder. Subsequent calls
overwrite the previous one.
§Examples
// Fixed 3 server processes
builder.processes(3, || Box::new(MyNode::new()))
// 3 to 7 processes, randomized per iteration
builder.processes(3..=7, || Box::new(MyNode::new()))Attach tag distribution to the last .processes() call.
Tags are distributed round-robin across process instances. Each tag dimension is distributed independently.
§Panics
Panics if called without a preceding .processes() call.
§Examples
// 5 processes: dc cycles east/west/eu, rack cycles r1/r2
builder.processes(5, || Box::new(MyNode::new()))
.tags(&[
("dc", &["east", "west", "eu"]),
("rack", &["r1", "r2"]),
])Sourcepub fn attrition(self, config: Attrition) -> Self
pub fn attrition(self, config: Attrition) -> Self
Set built-in attrition for automatic process reboots during chaos phase.
Attrition randomly kills and restarts server processes. It respects
max_dead to limit the number of simultaneously dead processes.
Requires .phases() — attrition injectors only run during
the chaos phase. Without a phase config, the injector will not be spawned.
For custom fault injection, use .fault() with a FaultInjector instead.
Sourcepub fn workloads(
self,
count: WorkloadCount,
factory: impl Fn(usize) -> Box<dyn Workload> + 'static,
) -> Self
pub fn workloads( self, count: WorkloadCount, factory: impl Fn(usize) -> Box<dyn Workload> + 'static, ) -> Self
Add multiple workload instances from a factory.
The factory receives an instance index (0-based) and must return a fresh workload. Instances are created each iteration and dropped afterward. Client IDs default to sequential starting from 0 (FDB-style).
The workload is responsible for its own name() — use the index to
produce unique names when count > 1 (e.g., format!("client-{i}")).
§Examples
// 3 fixed replicas
builder.workloads(WorkloadCount::Fixed(3), |i| Box::new(ReplicaWorkload::new(i)))
// 1–5 random clients
builder.workloads(WorkloadCount::Random(1..6), |i| Box::new(ClientWorkload::new(i)))Sourcepub fn workloads_with_client_id(
self,
count: WorkloadCount,
client_id: ClientId,
factory: impl Fn(usize) -> Box<dyn Workload> + 'static,
) -> Self
pub fn workloads_with_client_id( self, count: WorkloadCount, client_id: ClientId, factory: impl Fn(usize) -> Box<dyn Workload> + 'static, ) -> Self
Add multiple workload instances with a custom client ID strategy.
Like workloads(), but client IDs are assigned
according to the given ClientId strategy instead of sequential.
§Examples
// 3 clients with random IDs in [100..200)
builder.workloads_with_client_id(
WorkloadCount::Fixed(3),
ClientId::RandomRange(100..200),
|i| Box::new(ClientWorkload::new(i)),
)Sourcepub fn invariant(self, i: impl Invariant) -> Self
pub fn invariant(self, i: impl Invariant) -> Self
Add an invariant to be checked after every simulation event.
Sourcepub fn invariant_fn(
self,
name: impl Into<String>,
f: impl Fn(&StateHandle, u64) + 'static,
) -> Self
pub fn invariant_fn( self, name: impl Into<String>, f: impl Fn(&StateHandle, u64) + 'static, ) -> Self
Add a closure-based invariant.
Sourcepub fn fault(self, f: impl FaultInjector) -> Self
pub fn fault(self, f: impl FaultInjector) -> Self
Add a fault injector to run during the chaos phase.
Sourcepub fn phases(self, config: PhaseConfig) -> Self
pub fn phases(self, config: PhaseConfig) -> Self
Set two-phase chaos/recovery configuration.
Sourcepub fn set_iterations(self, iterations: usize) -> Self
pub fn set_iterations(self, iterations: usize) -> Self
Set the number of iterations to run.
Sourcepub fn set_iteration_control(self, control: IterationControl) -> Self
pub fn set_iteration_control(self, control: IterationControl) -> Self
Set the iteration control strategy.
Sourcepub fn set_time_limit(self, duration: Duration) -> Self
pub fn set_time_limit(self, duration: Duration) -> Self
Run for a specific wall-clock time duration.
Sourcepub fn until_converged(self, max_iterations: usize) -> Self
pub fn until_converged(self, max_iterations: usize) -> Self
Run until exploration has converged: all assert_sometimes! assertions
have been reached and no new coverage was found on the last seed.
Requires .enable_exploration() to be configured.
max_iterations is a safety cap to prevent infinite loops.
Sourcepub fn before_iteration(self, f: impl FnMut() + 'static) -> Self
pub fn before_iteration(self, f: impl FnMut() + 'static) -> Self
Register a callback invoked at the start of each simulation iteration.
Use this to reset shared state (directories, membership, stores) that
lives outside the builder and is shared via Rc across iterations.
Sourcepub fn set_debug_seeds(self, seeds: Vec<u64>) -> Self
pub fn set_debug_seeds(self, seeds: Vec<u64>) -> Self
Set specific seeds for deterministic debugging and regression testing.
Sourcepub fn random_network(self) -> Self
pub fn random_network(self) -> Self
Enable randomized network configuration for chaos testing.
Sourcepub fn enable_exploration(self, config: ExplorationConfig) -> Self
pub fn enable_exploration(self, config: ExplorationConfig) -> Self
Enable fork-based multiverse exploration.
When enabled, the simulation will fork child processes at assertion discovery points to explore alternate timelines with different seeds.
Sourcepub fn replay_recipe(self, recipe: BugRecipe) -> Self
pub fn replay_recipe(self, recipe: BugRecipe) -> Self
Set a bug recipe for deterministic replay.
The builder applies the recipe’s RNG breakpoints after its own initialization, ensuring they survive internal resets.
Sourcepub fn run(self) -> SimulationReport
pub fn run(self) -> SimulationReport
Run the simulation and generate a report.
Creates a fresh tokio LocalRuntime per iteration for full isolation —
all tasks are killed when the runtime is dropped at iteration end.