1use crate::LoadBalancer;
2use rand::seq::IteratorRandom;
3use std::future::Future;
4use std::sync::Arc;
5use std::time::Duration;
6use tokio::sync::RwLock;
7use tokio::task::JoinHandle;
8use tokio::{spawn, time::sleep};
9
10#[derive(Clone)]
11pub struct Entry<T>
12where
13 T: Send + Sync + Clone + 'static,
14{
15 pub value: T,
16}
17
18pub struct Inner<T>
19where
20 T: Send + Sync + Clone + 'static,
21{
22 pub entries: RwLock<Vec<Entry<T>>>,
23}
24
25#[derive(Clone)]
27pub struct Random<T>
28where
29 T: Send + Sync + Clone + 'static,
30{
31 inner: Arc<Inner<T>>,
32}
33
34impl<T> Random<T>
35where
36 T: Send + Sync + Clone + 'static,
37{
38 pub fn new(entries: Vec<T>) -> Self {
40 Self {
41 inner: Arc::new(Inner {
42 entries: RwLock::new(
43 entries.into_iter().map(|value| Entry { value }).collect(),
44 ),
45 }),
46 }
47 }
48
49 pub async fn update<F, R, N>(&self, handler: F) -> anyhow::Result<N>
51 where
52 F: Fn(Arc<Inner<T>>) -> R,
53 R: Future<Output = anyhow::Result<N>>,
54 {
55 handler(self.inner.clone()).await
56 }
57
58 pub async fn update_timer<F, R>(
63 &self,
64 handler: F,
65 interval: Duration,
66 ) -> anyhow::Result<JoinHandle<()>>
67 where
68 F: Fn(Arc<Inner<T>>) -> R + Send + Sync + 'static,
69 R: Future<Output = anyhow::Result<()>> + Send,
70 {
71 handler(self.inner.clone()).await?;
72
73 let inner = self.inner.clone();
74
75 Ok(spawn(async move {
76 loop {
77 sleep(interval).await;
78 let _ = handler(inner.clone()).await;
79 }
80 }))
81 }
82}
83
84impl<T> LoadBalancer<T> for Random<T>
85where
86 T: Send + Sync + Clone + 'static,
87{
88 async fn alloc(&self) -> T {
89 self.inner
90 .entries
91 .read()
92 .await
93 .iter()
94 .choose(&mut rand::rng())
95 .map(|v| v.value.clone())
96 .unwrap()
97 }
98
99 fn try_alloc(&self) -> Option<T> {
100 self.inner
101 .entries
102 .try_read()
103 .ok()?
104 .iter()
105 .choose(&mut rand::rng())
106 .map(|v| v.value.clone())
107 }
108}