| 1 |
|
| 2 |
|
| 3 |
use std::time::Duration; |
| 4 |
|
| 5 |
|
| 6 |
pub struct LoadConfig { |
| 7 |
|
| 8 |
pub virtual_users: u32, |
| 9 |
|
| 10 |
pub duration: Duration, |
| 11 |
|
| 12 |
pub ramp_up: Duration, |
| 13 |
|
| 14 |
pub think_time: Duration, |
| 15 |
|
| 16 |
pub db_max_connections: u32, |
| 17 |
|
| 18 |
pub db_acquire_timeout: Duration, |
| 19 |
|
| 20 |
pub scenario_mix: ScenarioMix, |
| 21 |
} |
| 22 |
|
| 23 |
impl LoadConfig { |
| 24 |
|
| 25 |
pub fn from_env() -> Self { |
| 26 |
let virtual_users = env_or("LOAD_VUS", 20); |
| 27 |
let duration = Duration::from_secs(env_or("LOAD_DURATION_SECS", 30)); |
| 28 |
let ramp_up = Duration::from_secs(env_or("LOAD_RAMP_SECS", 5)); |
| 29 |
let think_time = Duration::from_millis(env_or("LOAD_THINK_MS", 50)); |
| 30 |
|
| 31 |
LoadConfig { |
| 32 |
virtual_users, |
| 33 |
duration, |
| 34 |
ramp_up, |
| 35 |
think_time, |
| 36 |
db_max_connections: 10, |
| 37 |
db_acquire_timeout: Duration::from_secs(3), |
| 38 |
scenario_mix: ScenarioMix::default(), |
| 39 |
} |
| 40 |
} |
| 41 |
} |
| 42 |
|
| 43 |
|
| 44 |
#[derive(Debug)] |
| 45 |
pub struct ScenarioMix { |
| 46 |
pub anonymous_browse: u32, |
| 47 |
pub buyer_flow: u32, |
| 48 |
pub creator_flow: u32, |
| 49 |
pub dashboard_session: u32, |
| 50 |
} |
| 51 |
|
| 52 |
impl Default for ScenarioMix { |
| 53 |
fn default() -> Self { |
| 54 |
ScenarioMix { |
| 55 |
anonymous_browse: 60, |
| 56 |
buyer_flow: 20, |
| 57 |
creator_flow: 15, |
| 58 |
dashboard_session: 5, |
| 59 |
} |
| 60 |
} |
| 61 |
} |
| 62 |
|
| 63 |
impl ScenarioMix { |
| 64 |
|
| 65 |
pub fn assign_scenario(&self, vu_index: u32, total_vus: u32) -> ScenarioType { |
| 66 |
|
| 67 |
let pct = (vu_index as u64 * 100 / total_vus as u64) as u32; |
| 68 |
|
| 69 |
if pct < self.anonymous_browse { |
| 70 |
ScenarioType::AnonymousBrowse |
| 71 |
} else if pct < self.anonymous_browse + self.buyer_flow { |
| 72 |
ScenarioType::BuyerFlow |
| 73 |
} else if pct < self.anonymous_browse + self.buyer_flow + self.creator_flow { |
| 74 |
ScenarioType::CreatorFlow |
| 75 |
} else { |
| 76 |
ScenarioType::DashboardSession |
| 77 |
} |
| 78 |
} |
| 79 |
} |
| 80 |
|
| 81 |
#[derive(Debug, Clone, Copy)] |
| 82 |
pub enum ScenarioType { |
| 83 |
AnonymousBrowse, |
| 84 |
BuyerFlow, |
| 85 |
CreatorFlow, |
| 86 |
DashboardSession, |
| 87 |
} |
| 88 |
|
| 89 |
impl std::fmt::Display for ScenarioType { |
| 90 |
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { |
| 91 |
match self { |
| 92 |
ScenarioType::AnonymousBrowse => write!(f, "anonymous_browse"), |
| 93 |
ScenarioType::BuyerFlow => write!(f, "buyer_flow"), |
| 94 |
ScenarioType::CreatorFlow => write!(f, "creator_flow"), |
| 95 |
ScenarioType::DashboardSession => write!(f, "dashboard_session"), |
| 96 |
} |
| 97 |
} |
| 98 |
} |
| 99 |
|
| 100 |
fn env_or<T: std::str::FromStr>(key: &str, default: T) -> T { |
| 101 |
std::env::var(key) |
| 102 |
.ok() |
| 103 |
.and_then(|v| v.parse().ok()) |
| 104 |
.unwrap_or(default) |
| 105 |
} |
| 106 |
|