use rand::Rng;
use std::{env::var, str::FromStr};
#[derive(Debug, Clone, Copy)]
pub struct Chaos {
publisher_duplicate_percentage: u8,
publisher_failure_percentage: u8,
}
impl Chaos {
pub fn new() -> Self {
let configs = std::env::vars()
.filter(|(k, _)| k.starts_with("AMQPSY_CHAOS_"))
.count();
if configs == 0 {
panic!("amqpsy: When the `chaos` feature is turned on, you must start the app with one of the chaos parameter passed as environment variable (`AMQPSY_CHAOS_*`). See the `Chaos` section of the readme.")
}
Self {
publisher_duplicate_percentage: from_env_or_default(
"AMQPSY_CHAOS_PUBLISHER_DUPLICATE_PERCENTAGE",
),
publisher_failure_percentage: from_env_or_default(
"AMQPSY_CHAOS_PUBLISHER_FAILURE_PERCENTAGE",
),
}
}
pub fn should_publish_fail(&self) -> bool {
true_percentage_of_time(self.publisher_failure_percentage)
}
pub fn should_publish_duplicate(&self) -> bool {
true_percentage_of_time(self.publisher_duplicate_percentage)
}
}
fn from_env_or_default<T: FromStr + Default>(p: &str) -> T {
var(p)
.ok()
.and_then(|v| v.parse::<T>().ok())
.unwrap_or_default()
}
fn between<T>(min: T, max: T) -> T
where
T: rand::distributions::uniform::SampleUniform + Eq + PartialOrd,
{
rand::thread_rng().gen_range(min..max)
}
fn true_percentage_of_time(percent: u8) -> bool {
if percent == 0 {
return false;
}
debug_assert!(percent <= 100);
between(1, 100) <= percent as _
}