use std::sync::atomic::{AtomicUsize, Ordering};
use async_trait::async_trait;
use crate::error::ProxyResult;
use crate::strategy::{ProxyCandidate, RotationStrategy, healthy_candidates};
#[derive(Debug, Default)]
pub struct RoundRobinStrategy {
counter: AtomicUsize,
}
#[async_trait]
impl RotationStrategy for RoundRobinStrategy {
async fn select<'a>(
&self,
candidates: &'a [ProxyCandidate],
) -> ProxyResult<&'a ProxyCandidate> {
use crate::error::ProxyError;
let healthy = healthy_candidates(candidates);
if healthy.is_empty() {
return Err(ProxyError::AllProxiesUnhealthy);
}
let idx = self
.counter
.fetch_add(1, Ordering::Relaxed)
.wrapping_rem(healthy.len());
healthy
.get(idx)
.copied()
.ok_or(ProxyError::AllProxiesUnhealthy)
}
}