1use crate::{BoxLoadBalancer, LoadBalancer};
2use async_trait::async_trait;
3use rand::seq::IteratorRandom;
4use std::future::Future;
5use std::sync::Arc;
6use tokio::sync::RwLock;
7
8#[derive(Clone)]
10pub struct Entry<T>
11where
12 T: Send + Sync + Clone + 'static,
13{
14 pub value: T,
16}
17
18#[derive(Clone)]
20pub struct RandomLoadBalancer<T>
21where
22 T: Send + Sync + Clone + 'static,
23{
24 inner: Arc<RwLock<Vec<Entry<T>>>>,
26}
27
28impl<T> RandomLoadBalancer<T>
29where
30 T: Send + Sync + Clone + 'static,
31{
32 pub fn new(inner: Vec<T>) -> Self {
34 Self {
35 inner: Arc::new(RwLock::new(
36 inner.into_iter().map(|value| Entry { value }).collect(),
37 )),
38 }
39 }
40
41 pub async fn update<F, R>(&self, handle: F) -> anyhow::Result<()>
43 where
44 F: Fn(Arc<RwLock<Vec<Entry<T>>>>) -> R,
45 R: Future<Output = anyhow::Result<()>>,
46 {
47 handle(self.inner.clone()).await
48 }
49}
50
51impl<T> LoadBalancer<T> for RandomLoadBalancer<T>
52where
53 T: Send + Sync + Clone + 'static,
54{
55 async fn alloc(&self) -> Option<T> {
57 self.inner
58 .read()
59 .await
60 .iter()
61 .choose(&mut rand::rng())
62 .map(|v| v.value.clone())
63 }
64
65 fn try_alloc(&self) -> Option<T> {
67 self.inner
68 .try_read()
69 .ok()?
70 .iter()
71 .choose(&mut rand::rng())
72 .map(|v| v.value.clone())
73 }
74}
75
76#[async_trait]
77impl<T> BoxLoadBalancer<T> for RandomLoadBalancer<T>
78where
79 T: Send + Sync + Clone + 'static,
80{
81 async fn alloc(&self) -> Option<T> {
83 self.inner
84 .read()
85 .await
86 .iter()
87 .choose(&mut rand::rng())
88 .map(|v| v.value.clone())
89 }
90
91 fn try_alloc(&self) -> Option<T> {
93 self.inner
94 .try_read()
95 .ok()?
96 .iter()
97 .choose(&mut rand::rng())
98 .map(|v| v.value.clone())
99 }
100}