use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Deserialize, PartialEq, Eq, Serialize)]
#[serde(untagged)]
pub enum LoadBalancerStrategy {
Simple(SimpleStrategy),
Parameterised(ParameterisedStrategy),
}
impl Default for LoadBalancerStrategy {
fn default() -> Self {
Self::Simple(SimpleStrategy::RoundRobin)
}
}
#[derive(Debug, Clone, Default, Deserialize, PartialEq, Eq, Serialize)]
#[serde(rename_all = "snake_case")]
pub enum SimpleStrategy {
#[default]
RoundRobin,
LeastConnections,
}
#[derive(Debug, Clone, Deserialize, PartialEq, Eq, Serialize)]
pub enum ParameterisedStrategy {
#[serde(rename = "consistent_hash")]
ConsistentHash(ConsistentHashOpts),
}
#[derive(Debug, Clone, Default, Deserialize, PartialEq, Eq, Serialize)]
pub struct ConsistentHashOpts {
#[serde(default)]
pub header: Option<String>,
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn load_balancer_strategy_defaults_to_round_robin() {
assert_eq!(
LoadBalancerStrategy::default(),
LoadBalancerStrategy::Simple(SimpleStrategy::RoundRobin),
"default strategy should be round_robin"
);
}
#[test]
fn load_balancer_strategy_parses_round_robin() {
let yaml = "round_robin";
let strategy: LoadBalancerStrategy = serde_yaml::from_str(yaml).unwrap();
assert_eq!(
strategy,
LoadBalancerStrategy::Simple(SimpleStrategy::RoundRobin),
"should parse 'round_robin' string"
);
}
#[test]
fn load_balancer_strategy_parses_least_connections() {
let yaml = "least_connections";
let strategy: LoadBalancerStrategy = serde_yaml::from_str(yaml).unwrap();
assert_eq!(
strategy,
LoadBalancerStrategy::Simple(SimpleStrategy::LeastConnections),
"should parse 'least_connections' string"
);
}
#[test]
fn load_balancer_strategy_parses_consistent_hash() {
let yaml = r#"
consistent_hash:
header: "X-User-Id"
"#;
let strategy: LoadBalancerStrategy = serde_yaml::from_str(yaml).unwrap();
assert_eq!(
strategy,
LoadBalancerStrategy::Parameterised(ParameterisedStrategy::ConsistentHash(ConsistentHashOpts {
header: Some("X-User-Id".into()),
})),
"should parse consistent_hash with header"
);
}
#[test]
fn consistent_hash_without_header() {
let yaml = "consistent_hash: {}";
let strategy: LoadBalancerStrategy = serde_yaml::from_str(yaml).unwrap();
assert_eq!(
strategy,
LoadBalancerStrategy::Parameterised(ParameterisedStrategy::ConsistentHash(ConsistentHashOpts {
header: None,
})),
"should parse consistent_hash with no header"
);
}
}