1use crate::{ComponentManager, Keyed, WithArgs};
2use futures::future::join_all;
3
4impl<Key, Args, Comp, FnInit> ComponentManager<Key, Args, Comp, FnInit> {
5 pub async fn init_async(args: impl IntoIterator<Item = (Key, Args)>, init: FnInit) -> Self
6 where
7 Key: Eq + std::hash::Hash,
8 FnInit: AsyncFn(&Args) -> Comp + Clone,
9 {
10 let components_fut = args.into_iter().map(|(key, args)| {
11 let init = init.clone();
12 async move {
13 let component = (init)(&args).await;
14 (key, WithArgs { component, args })
15 }
16 });
17
18 let map = join_all(components_fut).await.into_iter().collect();
19
20 Self { map, init }
21 }
22
23 pub async fn reinit_all_async(&mut self) -> impl Iterator<Item = Keyed<&Key, Comp>>
24 where
25 Key: Clone,
26 FnInit: AsyncFn(&Args) -> Comp + Clone,
27 {
28 let next_components_fut = self
29 .map
30 .values()
31 .map(|component| (self.init)(&component.args));
32
33 let next_components = join_all(next_components_fut).await;
34
35 self.map
36 .iter_mut()
37 .zip(next_components)
38 .map(|((key, prev), next)| {
39 let prev = std::mem::replace(&mut prev.component, next);
40 Keyed::new(key, prev)
41 })
42 }
43
44 pub async fn reinit_async(
45 &mut self,
46 keys: impl IntoIterator<Item = Key>,
47 ) -> impl Iterator<Item = Keyed<Key, Option<Comp>>>
48 where
49 Key: Eq + std::hash::Hash + Clone,
50 FnInit: AsyncFn(&Args) -> Comp + Clone,
51 {
52 let next_components_fut = keys.into_iter().map(|key| {
53 let init = self.init.clone();
54 let args = self.map.get(&key).map(|component| &component.args);
55 async move {
56 let next = match args {
57 Some(args) => Some((init)(args).await),
58 None => None,
59 };
60 Keyed::new(key, next)
61 }
62 });
63
64 let results = join_all(next_components_fut).await;
65
66 results.into_iter().map(|Keyed { key, value: next }| {
67 let prev = next.and_then(|next| {
68 self.map
69 .get_mut(&key)
70 .map(|component| std::mem::replace(&mut component.component, next))
71 });
72 Keyed::new(key, prev)
73 })
74 }
75
76 pub async fn update_async(
77 &mut self,
78 updates: impl IntoIterator<Item = (Key, Args)>,
79 ) -> impl Iterator<Item = Keyed<Key, Option<WithArgs<Args, Comp>>>>
80 where
81 Key: Clone + Eq + std::hash::Hash,
82 FnInit: AsyncFn(&Args) -> Comp + Clone,
83 {
84 let updated_components_fut = updates.into_iter().map(|(key, args)| {
85 let init = self.init.clone();
86 async move {
87 let component = (init)(&args).await;
88 (key, WithArgs { component, args })
89 }
90 });
91
92 join_all(updated_components_fut)
93 .await
94 .into_iter()
95 .map(|(key, component)| {
96 let prev = self.map.insert(key.clone(), component);
97 Keyed::new(key, prev)
98 })
99 }
100}
101
102#[cfg(test)]
103mod tests {
104 use super::*;
105 use std::sync::{Arc, Mutex};
106
107 #[derive(Debug, Clone, PartialEq, Eq)]
108 struct Counter(usize);
109
110 #[derive(Debug, Clone, PartialEq, Eq)]
111 struct Args {
112 value: usize,
113 }
114
115 #[tokio::test]
116 async fn test_init_async() {
117 let init = |args: &Args| {
118 let value = args.value;
119 async move { Counter(value) }
120 };
121 let manager = ComponentManager::init_async(
122 [("key1", Args { value: 1 }), ("key2", Args { value: 2 })],
123 init,
124 )
125 .await;
126
127 assert_eq!(manager.components().len(), 2);
128 assert_eq!(
129 manager.components().get("key1").unwrap().component,
130 Counter(1)
131 );
132 assert_eq!(
133 manager.components().get("key2").unwrap().component,
134 Counter(2)
135 );
136 assert_eq!(manager.components().get("key1").unwrap().args.value, 1);
137 }
138
139 #[tokio::test]
140 async fn test_init_async_empty() {
141 let init = |args: &Args| {
142 let value = args.value;
143 async move { Counter(value) }
144 };
145 let manager: ComponentManager<&str, Args, Counter, _> =
146 ComponentManager::init_async([], init).await;
147
148 assert_eq!(manager.components().len(), 0);
149 }
150
151 #[tokio::test]
152 async fn test_reinit_all_async() {
153 let call_count = Arc::new(Mutex::new(0));
154 let call_count_clone = call_count.clone();
155
156 let init = move |args: &Args| {
157 let call_count = call_count_clone.clone();
158 let value = args.value;
159 async move {
160 *call_count.lock().unwrap() += 1;
161 Counter(value * 2)
162 }
163 };
164
165 let mut manager = ComponentManager::init_async(
166 [("key1", Args { value: 1 }), ("key2", Args { value: 2 })],
167 init,
168 )
169 .await;
170
171 let prev_components: Vec<_> = manager.reinit_all_async().await.collect();
172
173 assert_eq!(prev_components.len(), 2);
174 assert_eq!(
175 manager.components().get("key1").unwrap().component,
176 Counter(2)
177 );
178 assert_eq!(
179 manager.components().get("key2").unwrap().component,
180 Counter(4)
181 );
182
183 assert_eq!(*call_count.lock().unwrap(), 4);
185 }
186
187 #[tokio::test]
188 async fn test_reinit_all_async_empty() {
189 let init = |args: &Args| {
190 let value = args.value;
191 async move { Counter(value) }
192 };
193 let mut manager: ComponentManager<&str, Args, Counter, _> =
194 ComponentManager::init_async([], init).await;
195
196 let results: Vec<_> = manager.reinit_all_async().await.collect();
197 assert_eq!(results.len(), 0);
198 }
199
200 #[tokio::test]
201 async fn test_reinit_async_existing_key() {
202 let init = |args: &Args| {
203 let value = args.value;
204 async move { Counter(value * 2) }
205 };
206
207 let mut manager = ComponentManager::init_async(
208 [("key1", Args { value: 1 }), ("key2", Args { value: 2 })],
209 init,
210 )
211 .await;
212
213 let results: Vec<_> = manager.reinit_async(["key1"]).await.collect();
214
215 assert_eq!(results.len(), 1);
216 assert_eq!(results[0].key, "key1");
217 assert_eq!(results[0].value, Some(Counter(2)));
218
219 assert_eq!(
220 manager.components().get("key1").unwrap().component,
221 Counter(2)
222 );
223 assert_eq!(
224 manager.components().get("key2").unwrap().component,
225 Counter(4)
226 );
227 }
228
229 #[tokio::test]
230 async fn test_reinit_async_multiple_keys() {
231 let init = |args: &Args| {
232 let value = args.value;
233 async move { Counter(value * 3) }
234 };
235
236 let mut manager = ComponentManager::init_async(
237 [
238 ("key1", Args { value: 1 }),
239 ("key2", Args { value: 2 }),
240 ("key3", Args { value: 3 }),
241 ],
242 init,
243 )
244 .await;
245
246 let results: Vec<_> = manager.reinit_async(["key1", "key3"]).await.collect();
247
248 assert_eq!(results.len(), 2);
249 assert_eq!(
250 manager.components().get("key1").unwrap().component,
251 Counter(3)
252 );
253 assert_eq!(
254 manager.components().get("key2").unwrap().component,
255 Counter(6)
256 );
257 assert_eq!(
258 manager.components().get("key3").unwrap().component,
259 Counter(9)
260 );
261 }
262
263 #[tokio::test]
264 async fn test_reinit_async_nonexistent_key() {
265 let init = |args: &Args| {
266 let value = args.value;
267 async move { Counter(value) }
268 };
269
270 let mut manager = ComponentManager::init_async([("key1", Args { value: 1 })], init).await;
271
272 let results: Vec<_> = manager.reinit_async(["nonexistent"]).await.collect();
273
274 assert_eq!(results.len(), 1);
275 assert_eq!(results[0].key, "nonexistent");
276 assert_eq!(results[0].value, None);
277 assert_eq!(manager.components().len(), 1);
278 }
279
280 #[tokio::test]
281 async fn test_update_async_existing() {
282 let init = |args: &Args| {
283 let value = args.value;
284 async move { Counter(value) }
285 };
286
287 let mut manager = ComponentManager::init_async([("key1", Args { value: 1 })], init).await;
288
289 let results: Vec<_> = manager
290 .update_async([("key1", Args { value: 10 })])
291 .await
292 .collect();
293
294 assert_eq!(results.len(), 1);
295 assert_eq!(results[0].key, "key1");
296 assert!(results[0].value.is_some());
297 assert_eq!(results[0].value.as_ref().unwrap().component, Counter(1));
298
299 assert_eq!(
300 manager.components().get("key1").unwrap().component,
301 Counter(10)
302 );
303 assert_eq!(manager.components().get("key1").unwrap().args.value, 10);
304 }
305
306 #[tokio::test]
307 async fn test_update_async_new_key() {
308 let init = |args: &Args| {
309 let value = args.value;
310 async move { Counter(value) }
311 };
312
313 let mut manager = ComponentManager::init_async([("key1", Args { value: 1 })], init).await;
314
315 let results: Vec<_> = manager
316 .update_async([("key2", Args { value: 20 })])
317 .await
318 .collect();
319
320 assert_eq!(results.len(), 1);
321 assert_eq!(results[0].key, "key2");
322 assert!(results[0].value.is_none());
323
324 assert_eq!(manager.components().len(), 2);
325 assert_eq!(
326 manager.components().get("key2").unwrap().component,
327 Counter(20)
328 );
329 }
330
331 #[tokio::test]
332 async fn test_update_async_multiple() {
333 let init = |args: &Args| {
334 let value = args.value;
335 async move { Counter(value) }
336 };
337
338 let mut manager = ComponentManager::init_async([("key1", Args { value: 1 })], init).await;
339
340 let results: Vec<_> = manager
341 .update_async([
342 ("key1", Args { value: 10 }),
343 ("key2", Args { value: 20 }),
344 ("key3", Args { value: 30 }),
345 ])
346 .await
347 .collect();
348
349 assert_eq!(results.len(), 3);
350 assert_eq!(manager.components().len(), 3);
351 assert_eq!(
352 manager.components().get("key1").unwrap().component,
353 Counter(10)
354 );
355 assert_eq!(
356 manager.components().get("key2").unwrap().component,
357 Counter(20)
358 );
359 assert_eq!(
360 manager.components().get("key3").unwrap().component,
361 Counter(30)
362 );
363 }
364}