wd_balancing 0.0.4

A practical load balancing library for rust
Documentation
use tokio::sync::{RwLock, Mutex};
use std::sync::atomic::{AtomicUsize, Ordering};
use crate::BalancingStrategy;
use std::ops::{DerefMut, Deref};
use rand::Rng;

pub struct Random<K>{
    rng:Mutex<rand::rngs::OsRng>,
    scope:AtomicUsize,
    list:RwLock<Vec<(K,usize)>>
}
impl<K:Clone + Eq + Send + Sync > Random<K>{
    pub fn new()->Self{
        let rng =Mutex::new(rand::rngs::OsRng::default());
        let scope = AtomicUsize::new(0);
        let list= RwLock::new(vec![]);
        Self{rng,scope,list}
    }
    pub async fn rand(&self)->usize{
        let mut r = self.rng.lock().await;
        let r = r.deref_mut();
        r.gen_range(0..self.scope.load(Ordering::Relaxed))
    }
}
#[async_trait::async_trait]
impl<K:Clone + Eq + Send + Sync > BalancingStrategy<K> for Random<K>{
    async fn add(&self, k: K, n: usize) {
        if n <= 0{
            return;
        }
        let mut list = self.list.write().await;
        let list = list.deref_mut();
        list.push((k,n));
        self.scope.fetch_add(n,Ordering::Relaxed);
    }

    async fn remove(&self, k: K) {
        let mut list = self.list.write().await;
        let list = list.deref_mut();
        if list.len() < 1 {
            return
        }
        for index in 0..list.len(){
            if k == list[index].0 {
                self.scope.fetch_sub(list[index].1,Ordering::Relaxed);
                list.remove(index);
                break;
            }
        }
    }

    async fn select(&self) -> Option<K> {
        let list = self.list.read().await;
        let list = list.deref();
        if list.len() < 1 {
            return None
        }
        let mut number = self.rand().await;
        for index in 0..list.len() {
            if number < list[index].1 {
                return Some(list[index].0.clone())
            }else{
                number -= list[index].1;
            }
        }
        None
    }
}