1use std::{
4 collections::HashMap,
5 hash::Hash,
6 sync::{Arc, Mutex},
7 time::{Duration, Instant},
8};
9use tokio::sync::Semaphore;
10
11#[derive(Debug, Clone)]
13pub struct BatchConfig {
14 pub batch_size: usize,
15 pub timeout: Duration,
16}
17
18impl Default for BatchConfig {
19 fn default() -> Self {
20 Self {
21 batch_size: 100,
22 timeout: Duration::from_secs(5),
23 }
24 }
25}
26
27pub async fn batch_execute<T, F, Fut, R>(items: Vec<T>, config: BatchConfig, f: F) -> Vec<R>
29where
30 F: Fn(Vec<T>) -> Fut,
31 Fut: std::future::Future<Output = Vec<R>>,
32 T: Clone,
33{
34 let mut results = Vec::new();
35
36 for chunk in items.chunks(config.batch_size) {
37 let batch_results = tokio::time::timeout(config.timeout, f(chunk.to_vec()))
38 .await
39 .unwrap_or_else(|_| vec![]);
40
41 results.extend(batch_results);
42 }
43
44 results
45}
46
47pub async fn parallel_execute<T, F, Fut, R>(items: Vec<T>, concurrency: usize, f: F) -> Vec<R>
49where
50 F: Fn(T) -> Fut + Send + Sync,
51 Fut: std::future::Future<Output = R> + Send,
52 T: Send,
53 R: Send,
54{
55 let semaphore = Arc::new(Semaphore::new(concurrency));
56 let f = Arc::new(f);
57
58 let futures = items.into_iter().map(|item| {
59 let semaphore = semaphore.clone();
60 let f = f.clone();
61
62 async move {
63 let _permit = semaphore
65 .acquire()
66 .await
67 .expect("Semaphore should not be closed");
68 f(item).await
69 }
70 });
71
72 futures::future::join_all(futures).await
73}
74
75#[derive(Debug, Clone)]
77pub struct AsyncMemo<K, V> {
78 cache: Arc<Mutex<HashMap<K, (V, Instant)>>>,
79 ttl: Option<Duration>,
80}
81
82impl<K: Hash + Eq + Clone, V: Clone> Default for AsyncMemo<K, V> {
83 fn default() -> Self {
84 Self::new()
85 }
86}
87
88impl<K: Hash + Eq + Clone, V: Clone> AsyncMemo<K, V> {
89 pub fn new() -> Self {
90 Self {
91 cache: Arc::new(Mutex::new(HashMap::new())),
92 ttl: None,
93 }
94 }
95
96 pub fn with_ttl(ttl: Duration) -> Self {
97 Self {
98 cache: Arc::new(Mutex::new(HashMap::new())),
99 ttl: Some(ttl),
100 }
101 }
102
103 pub async fn get_or_compute<F, Fut>(&self, key: K, compute: F) -> V
104 where
105 F: FnOnce() -> Fut,
106 Fut: std::future::Future<Output = V>,
107 {
108 if let Some((value, timestamp)) = self.get_cached(&key) {
110 if let Some(ttl) = self.ttl {
111 if timestamp.elapsed() < ttl {
112 return value;
113 }
114 } else {
115 return value;
116 }
117 }
118
119 let value = compute().await;
121 self.insert(key, value.clone());
122 value
123 }
124
125 fn get_cached(&self, key: &K) -> Option<(V, Instant)> {
126 self.cache
127 .lock()
128 .expect("Cache mutex should not be poisoned")
129 .get(key)
130 .cloned()
131 }
132
133 fn insert(&self, key: K, value: V) {
134 self.cache
135 .lock()
136 .expect("Cache mutex should not be poisoned")
137 .insert(key, (value, Instant::now()));
138 }
139
140 pub fn clear(&self) {
141 self.cache
142 .lock()
143 .expect("Cache mutex should not be poisoned")
144 .clear();
145 }
146}
147
148#[derive(Debug)]
150pub struct ConnectionPool<T> {
151 available: Arc<Semaphore>,
152 max_size: usize,
153 _phantom: std::marker::PhantomData<T>,
154}
155
156impl<T> ConnectionPool<T> {
157 pub fn new(connections: Vec<T>) -> Self {
158 let max_size = connections.len();
159 let available = Arc::new(Semaphore::new(max_size));
160
161 Self {
162 available,
163 max_size,
164 _phantom: std::marker::PhantomData,
165 }
166 }
167
168 pub async fn acquire(&self) -> ConnectionGuard<'_, T> {
169 let permit = self
170 .available
171 .acquire()
172 .await
173 .expect("Connection pool semaphore should not be closed");
174 ConnectionGuard { permit, pool: self }
175 }
176
177 pub fn size(&self) -> usize {
178 self.max_size
179 }
180
181 pub fn available_connections(&self) -> usize {
182 self.available.available_permits()
183 }
184}
185
186pub struct ConnectionGuard<'a, T> {
188 #[allow(dead_code)]
189 permit: tokio::sync::SemaphorePermit<'a>,
190 #[allow(dead_code)]
191 pool: &'a ConnectionPool<T>,
192}
193
194#[derive(Debug)]
196pub struct RateLimiter {
197 semaphore: Arc<Semaphore>,
198 interval: Duration,
199}
200
201impl RateLimiter {
202 pub fn new(max_requests: usize, interval: Duration) -> Self {
203 Self {
204 semaphore: Arc::new(Semaphore::new(max_requests)),
205 interval,
206 }
207 }
208
209 pub async fn acquire(&self) -> RateLimitGuard {
210 let permit = self
211 .semaphore
212 .clone()
213 .acquire_owned()
214 .await
215 .expect("Rate limiter semaphore should not be closed");
216
217 let interval = self.interval;
219
220 tokio::spawn(async move {
221 tokio::time::sleep(interval).await;
222 drop(permit);
224 });
225
226 RateLimitGuard
227 }
228}
229
230pub struct RateLimitGuard;
232
233#[cfg(test)]
234mod tests {
235 use super::*;
236
237 #[test]
238 fn test_connection_pool() {
239 let connections = vec!["conn1", "conn2", "conn3"];
240 let pool = ConnectionPool::new(connections);
241
242 assert_eq!(pool.size(), 3);
243 assert_eq!(pool.available_connections(), 3);
244 }
245
246 #[test]
247 fn test_async_memo() {
248 let _memo = AsyncMemo::<String, i32>::new();
249 }
250
251 #[tokio::test]
252 async fn test_parallel_execute() {
253 let items = vec![1, 2, 3, 4, 5];
254 let results = parallel_execute(
255 items,
256 2, |x| async move { x * 2 },
258 )
259 .await;
260
261 assert_eq!(results, vec![2, 4, 6, 8, 10]);
262 }
263
264 #[tokio::test]
265 async fn test_async_memo_with_ttl() {
266 let memo = AsyncMemo::<String, i32>::with_ttl(Duration::from_millis(100));
267
268 let result1 = memo
269 .get_or_compute("key1".to_string(), || async { 42 })
270 .await;
271
272 assert_eq!(result1, 42);
273 }
274
275 #[tokio::test]
276 async fn test_rate_limiter() {
277 let limiter = RateLimiter::new(2, Duration::from_millis(100));
278
279 let _guard1 = limiter.acquire().await;
280 let _guard2 = limiter.acquire().await;
281
282 let start = Instant::now();
284 let _guard3 = limiter.acquire().await;
285 let elapsed = start.elapsed();
286
287 assert!(elapsed >= Duration::from_millis(50)); }
290}