use log::debug;
use rand::Rng;
use crate::load_balancer::tracker::InstanceTracker;
pub trait LoadBalancingStrategy {
fn select_instance(&mut self, trackers: &[(usize, &InstanceTracker)]) -> usize;
}
pub struct LeastRecentlyUsedStrategy;
impl LeastRecentlyUsedStrategy {
pub fn new() -> Self {
Self {}
}
}
impl LoadBalancingStrategy for LeastRecentlyUsedStrategy {
fn select_instance(&mut self, trackers: &[(usize, &InstanceTracker)]) -> usize {
if trackers.is_empty() {
panic!("LoadBalancingStrategy::select_instance called with empty trackers slice");
}
let mut oldest_index = 0;
let mut oldest_time = trackers[0].1.last_used;
for (i, (_id, tracker)) in trackers.iter().enumerate().skip(1) {
if tracker.last_used < oldest_time {
oldest_index = i;
oldest_time = tracker.last_used;
}
}
debug!(
"LeastRecentlyUsedStrategy: Selected index {} (ID: {}) from {} eligible trackers with last_used: {:?}",
oldest_index, trackers[oldest_index].0, trackers.len(), oldest_time
);
oldest_index
}
}
#[derive(Debug, Default)]
pub struct LowestLatencyStrategy;
impl LowestLatencyStrategy {
pub fn new() -> Self {
Self {}
}
}
impl LoadBalancingStrategy for LowestLatencyStrategy {
fn select_instance(&mut self, trackers: &[(usize, &InstanceTracker)]) -> usize {
if trackers.is_empty() {
panic!("LowestLatencyStrategy::select_instance called with empty trackers slice");
}
let mut best_index = 0;
let mut lowest_time = trackers[0].1.avg_response_time();
for (i, (_id, tracker)) in trackers.iter().enumerate().skip(1) {
let avg_time = tracker.avg_response_time();
if avg_time < lowest_time {
best_index = i;
lowest_time = avg_time;
}
}
debug!(
"LowestLatencyStrategy: Selected index {} (ID: {}) from {} eligible trackers with avg_response_time: {:?}",
best_index, trackers[best_index].0, trackers.len(), lowest_time
);
best_index
}
}
#[derive(Debug, Default)]
pub struct RandomStrategy;
impl RandomStrategy {
pub fn new() -> Self {
Self {}
}
}
impl LoadBalancingStrategy for RandomStrategy {
fn select_instance(&mut self, trackers: &[(usize, &InstanceTracker)]) -> usize {
if trackers.is_empty() {
panic!("RandomStrategy::select_instance called with empty trackers slice");
}
let index = rand::rng().random_range(0..trackers.len());
debug!(
"RandomStrategy: Selected random index {} (ID: {}) from {} eligible trackers",
index, trackers[index].0, trackers.len()
);
index
}
}