1use std::future::Future;
8
9use async_broadcast::{Receiver, RecvError};
10use futures::{
11 FutureExt,
12 future::BoxFuture,
13 stream::{FuturesUnordered, StreamExt},
14};
15
16pub trait Dependency<T> {
18 fn completed(self) -> impl Future<Output = Option<T>> + Send;
20 fn or<D: Dependency<T> + Send + 'static>(self, dep: D) -> OrDependency<T>
22 where
23 T: Send + Sync + Clone + 'static,
24 Self: Sized + Send + 'static,
25 {
26 let mut or = OrDependency::from_deps(vec![self]);
27 or.add_dep(dep);
28 or
29 }
30 fn and<D: Dependency<T> + Send + 'static>(self, dep: D) -> AndDependency<T>
32 where
33 T: Send + Sync + Clone + 'static,
34 Self: Sized + Send + 'static,
35 {
36 let mut and = AndDependency::from_deps(vec![self]);
37 and.add_dep(dep);
38 and
39 }
40}
41
42pub struct AndDependency<T> {
44 deps: Vec<BoxFuture<'static, Option<T>>>,
46}
47impl<T: Clone + Send + Sync> Dependency<Vec<T>> for AndDependency<T> {
48 async fn completed(self) -> Option<Vec<T>> {
51 let futures = FuturesUnordered::from_iter(self.deps);
52 futures
53 .collect::<Vec<Option<T>>>()
54 .await
55 .into_iter()
56 .collect()
57 }
58}
59
60impl<T: Clone + Send + Sync + 'static> AndDependency<T> {
61 #[must_use]
63 pub fn from_deps(deps: Vec<impl Dependency<T> + Send + 'static>) -> Self {
64 let mut pinned = vec![];
65 for dep in deps {
66 pinned.push(dep.completed().boxed());
67 }
68 Self { deps: pinned }
69 }
70 pub fn add_dep(&mut self, dep: impl Dependency<T> + Send + 'static) {
72 self.deps.push(dep.completed().boxed());
73 }
74 pub fn add_deps(&mut self, deps: AndDependency<T>) {
76 for dep in deps.deps {
77 self.deps.push(dep);
78 }
79 }
80}
81
82pub struct OrDependency<T> {
84 deps: Vec<BoxFuture<'static, Option<T>>>,
86}
87impl<T: Clone + Send + Sync> Dependency<T> for OrDependency<T> {
88 async fn completed(self) -> Option<T> {
90 let mut futures = FuturesUnordered::from_iter(self.deps);
91 loop {
92 let maybe = futures.next().await?;
93 if maybe.is_some() {
94 return maybe;
95 }
96 }
97 }
98}
99
100impl<T: Clone + Send + Sync + 'static> OrDependency<T> {
101 #[must_use]
103 pub fn from_deps(deps: Vec<impl Dependency<T> + Send + 'static>) -> Self {
104 let mut pinned = vec![];
105 for dep in deps {
106 pinned.push(dep.completed().boxed());
107 }
108 Self { deps: pinned }
109 }
110 pub fn add_dep(&mut self, dep: impl Dependency<T> + Send + 'static) {
112 self.deps.push(dep.completed().boxed());
113 }
114}
115
116pub struct EventDependency<T: Clone + Send + Sync> {
119 pub(crate) event_rx: Receiver<T>,
121
122 pub(crate) match_fn: Box<dyn Fn(&T) -> bool + Send>,
125
126 completed_dependency: Option<T>,
129
130 cancel_receiver: Receiver<()>,
131
132 dependency_name: String,
133}
134
135impl<T: Clone + Send + Sync + 'static> EventDependency<T> {
136 #[must_use]
138 pub fn new(
139 receiver: Receiver<T>,
140 cancel_receiver: Receiver<()>,
141 dependency_name: String,
142 match_fn: Box<dyn Fn(&T) -> bool + Send>,
143 ) -> Self {
144 Self {
145 event_rx: receiver,
146 match_fn: Box::new(match_fn),
147 completed_dependency: None,
148 cancel_receiver,
149 dependency_name,
150 }
151 }
152
153 pub fn mark_as_completed(&mut self, dependency: T) {
155 self.completed_dependency = Some(dependency);
156 }
157}
158
159impl<T: Clone + Send + Sync + 'static> Dependency<T> for EventDependency<T> {
160 async fn completed(mut self) -> Option<T> {
161 if let Some(dependency) = self.completed_dependency {
162 return Some(dependency);
163 }
164 loop {
165 if let Some(dependency) = self.completed_dependency {
166 return Some(dependency);
167 }
168
169 tokio::select! {
170 recv_event = self.event_rx.recv() => {
171 match recv_event {
172 Ok(event) => {
173 if (self.match_fn)(&event) {
174 return Some(event);
175 }
176 },
177 Err(RecvError::Overflowed(n)) => {
178 tracing::error!("Dependency Task overloaded, skipping {} events", n);
179 },
180 Err(RecvError::Closed) => {
181 return None;
182 },
183 }
184 }
185 _ = self.cancel_receiver.recv() => {
186 tracing::warn!("{} dependency cancelled", self.dependency_name);
187 return None;
188 }
189 }
190 }
191 }
192}
193
194#[cfg(test)]
195mod tests {
196 use async_broadcast::{Receiver, broadcast};
197
198 use super::{AndDependency, Dependency, EventDependency, OrDependency};
199
200 fn eq_dep(
201 rx: Receiver<usize>,
202 cancel_rx: Receiver<()>,
203 dep_name: String,
204 val: usize,
205 ) -> EventDependency<usize> {
206 EventDependency {
207 event_rx: rx,
208 match_fn: Box::new(move |v| *v == val),
209 completed_dependency: None,
210 dependency_name: dep_name,
211 cancel_receiver: cancel_rx,
212 }
213 }
214
215 #[tokio::test(flavor = "multi_thread")]
216 async fn it_works() {
217 let (tx, rx) = broadcast(10);
218 let (_cancel_tx, cancel_rx) = broadcast(1);
219
220 let mut deps = vec![];
221 for i in 0..5 {
222 tx.broadcast(i).await.unwrap();
223 deps.push(eq_dep(
224 rx.clone(),
225 cancel_rx.clone(),
226 format!("it_works {i}"),
227 5,
228 ));
229 }
230
231 let and = AndDependency::from_deps(deps);
232 tx.broadcast(5).await.unwrap();
233 let result = and.completed().await;
234 assert_eq!(result, Some(vec![5; 5]));
235 }
236
237 #[tokio::test(flavor = "multi_thread")]
238 async fn or_dep() {
239 let (tx, rx) = broadcast(10);
240 let (_cancel_tx, cancel_rx) = broadcast(1);
241
242 tx.broadcast(5).await.unwrap();
243 let mut deps = vec![];
244 for i in 0..5 {
245 deps.push(eq_dep(
246 rx.clone(),
247 cancel_rx.clone(),
248 format!("or_dep {i}"),
249 5,
250 ));
251 }
252 let or = OrDependency::from_deps(deps);
253 let result = or.completed().await;
254 assert_eq!(result, Some(5));
255 }
256
257 #[tokio::test(flavor = "multi_thread")]
258 async fn and_or_dep() {
259 let (tx, rx) = broadcast(10);
260 let (_cancel_tx, cancel_rx) = broadcast(1);
261
262 tx.broadcast(1).await.unwrap();
263 tx.broadcast(2).await.unwrap();
264 tx.broadcast(3).await.unwrap();
265 tx.broadcast(5).await.unwrap();
266 tx.broadcast(6).await.unwrap();
267
268 let or1 = OrDependency::from_deps(
269 [
270 eq_dep(
271 rx.clone(),
272 cancel_rx.clone(),
273 format!("and_or_dep or1 {}", 4),
274 4,
275 ),
276 eq_dep(
277 rx.clone(),
278 cancel_rx.clone(),
279 format!("and_or_dep or1 {}", 6),
280 6,
281 ),
282 ]
283 .into(),
284 );
285 let or2 = OrDependency::from_deps(
286 [
287 eq_dep(
288 rx.clone(),
289 cancel_rx.clone(),
290 format!("and_or_dep or2 {}", 4),
291 4,
292 ),
293 eq_dep(
294 rx.clone(),
295 cancel_rx.clone(),
296 format!("and_or_dep or2 {}", 5),
297 5,
298 ),
299 ]
300 .into(),
301 );
302 let and = AndDependency::from_deps([or1, or2].into());
303 let result = and.completed().await;
304 assert_eq!(result, Some(vec![6, 5]));
305 }
306
307 #[tokio::test(flavor = "multi_thread")]
308 async fn or_and_dep() {
309 let (tx, rx) = broadcast(10);
310 let (_cancel_tx, cancel_rx) = broadcast(1);
311
312 tx.broadcast(1).await.unwrap();
313 tx.broadcast(2).await.unwrap();
314 tx.broadcast(3).await.unwrap();
315 tx.broadcast(4).await.unwrap();
316 tx.broadcast(5).await.unwrap();
317
318 let and1 = eq_dep(
319 rx.clone(),
320 cancel_rx.clone(),
321 format!("or_and_dep and1 {}", 4),
322 4,
323 )
324 .and(eq_dep(
325 rx.clone(),
326 cancel_rx.clone(),
327 format!("or_and_dep and1 {}", 6),
328 6,
329 ));
330 let and2 = eq_dep(
331 rx.clone(),
332 cancel_rx.clone(),
333 format!("or_and_dep and2 {}", 4),
334 4,
335 )
336 .and(eq_dep(
337 rx.clone(),
338 cancel_rx.clone(),
339 format!("or_and_dep and2 {}", 5),
340 5,
341 ));
342 let or = and1.or(and2);
343 let result = or.completed().await;
344 assert_eq!(result, Some(vec![4, 5]));
345 }
346
347 #[tokio::test(flavor = "multi_thread")]
348 async fn many_and_dep() {
349 let (tx, rx) = broadcast(10);
350 let (_cancel_tx, cancel_rx) = broadcast(1);
351
352 tx.broadcast(1).await.unwrap();
353 tx.broadcast(2).await.unwrap();
354 tx.broadcast(3).await.unwrap();
355 tx.broadcast(4).await.unwrap();
356 tx.broadcast(5).await.unwrap();
357 tx.broadcast(6).await.unwrap();
358
359 let mut and1 = eq_dep(
360 rx.clone(),
361 cancel_rx.clone(),
362 format!("many_and_dep and1 {}", 4),
363 4,
364 )
365 .and(eq_dep(
366 rx.clone(),
367 cancel_rx.clone(),
368 format!("many_and_dep and1 {}", 6),
369 6,
370 ));
371 let and2 = eq_dep(
372 rx.clone(),
373 cancel_rx.clone(),
374 format!("many_and_dep and2 {}", 4),
375 4,
376 )
377 .and(eq_dep(
378 rx.clone(),
379 cancel_rx.clone(),
380 format!("many_and_dep and2 {}", 5),
381 5,
382 ));
383 and1.add_deps(and2);
384 let result = and1.completed().await;
385 assert_eq!(result, Some(vec![4, 6, 4, 5]));
386 }
387
388 #[tokio::test(flavor = "multi_thread")]
389 async fn cancel_event_dep() {
390 let (tx, rx) = broadcast(10);
391 let (cancel_tx, cancel_rx) = broadcast(1);
392
393 for i in 0..=5 {
394 tx.broadcast(i).await.unwrap();
395 }
396 cancel_tx.broadcast(()).await.unwrap();
397 let dep = eq_dep(
398 rx.clone(),
399 cancel_rx.clone(),
400 format!("cancel_event_dep {}", 6),
401 6,
402 );
403 let result = dep.completed().await;
404 assert_eq!(result, None);
405 }
406
407 #[tokio::test(flavor = "multi_thread")]
408 async fn drop_cancel_dep() {
409 let (tx, rx) = broadcast(10);
410 let (cancel_tx, cancel_rx) = broadcast(1);
411
412 for i in 0..=5 {
413 tx.broadcast(i).await.unwrap();
414 }
415 drop(cancel_tx);
416 let dep = eq_dep(
417 rx.clone(),
418 cancel_rx.clone(),
419 format!("drop_cancel_dep {}", 6),
420 6,
421 );
422 let result = dep.completed().await;
423 assert_eq!(result, None);
424 }
425
426 #[tokio::test(flavor = "multi_thread")]
427 async fn cancel_and_dep() {
428 let (tx, rx) = broadcast(10);
429 let (cancel_tx, cancel_rx) = broadcast(1);
430
431 let mut deps = vec![];
432 for i in 0..=5 {
433 tx.broadcast(i).await.unwrap();
434 deps.push(eq_dep(
435 rx.clone(),
436 cancel_rx.clone(),
437 format!("cancel_and_dep {i}"),
438 i,
439 ))
440 }
441 deps.push(eq_dep(
442 rx.clone(),
443 cancel_rx.clone(),
444 format!("cancel_and_dep {}", 6),
445 6,
446 ));
447 cancel_tx.broadcast(()).await.unwrap();
448 let result = AndDependency::from_deps(deps).completed().await;
449 assert_eq!(result, None);
450 }
451
452 #[tokio::test(flavor = "multi_thread")]
453 async fn cancel_or_dep() {
454 let (_, rx) = broadcast(10);
455 let (cancel_tx, cancel_rx) = broadcast(1);
456
457 let mut deps = vec![];
458 for i in 0..=5 {
459 deps.push(eq_dep(
460 rx.clone(),
461 cancel_rx.clone(),
462 format!("cancel_event_dep {i}"),
463 i,
464 ))
465 }
466 cancel_tx.broadcast(()).await.unwrap();
467 let result = OrDependency::from_deps(deps).completed().await;
468 assert_eq!(result, None);
469 }
470}