monoloop_testkit/
distribute.rs1use monoloop_contracts::InterpreterOutputEvent;
7use monoloop_loop::{CanonicalEventSubscription, SubscriptionPublisher, SubscriptionStatus};
8use std::sync::Arc;
9use tokio::sync::mpsc;
10
11#[derive(Clone, Copy, Debug, PartialEq, Eq)]
13pub enum SubscriberPolicy {
14 Lossless,
16 BestEffort,
18}
19
20struct Sub {
22 name: String,
23 policy: SubscriberPolicy,
24 pub_: SubscriptionPublisher,
25}
26
27pub struct EventDistributor {
29 subs: Vec<Sub>,
30}
31
32impl EventDistributor {
33 pub fn new() -> Self {
35 Self { subs: Vec::new() }
36 }
37
38 pub fn subscribe(
40 &mut self,
41 name: impl Into<String>,
42 policy: SubscriberPolicy,
43 capacity: usize,
44 ) -> CanonicalEventSubscription {
45 let name = name.into();
46 let (pub_, sub) = SubscriptionPublisher::channel(name.clone(), capacity);
47 self.subs.push(Sub { name, policy, pub_ });
48 sub
49 }
50
51 pub async fn publish(&self, event: InterpreterOutputEvent) {
53 for sub in &self.subs {
54 match sub.policy {
55 SubscriberPolicy::Lossless => {
56 let _ = sub.pub_.publish(event.clone()).await;
58 }
59 SubscriberPolicy::BestEffort => {
60 let _ = sub.pub_.publish(event.clone()).await;
63 }
64 }
65 }
66 }
67
68 pub fn close(self) {
70 drop(self.subs);
71 }
72}
73
74impl Default for EventDistributor {
75 fn default() -> Self {
76 Self::new()
77 }
78}
79
80pub async fn pump_interpreter_to_distributor(
82 events: Arc<monoloop_interpreter::CanonicalEventStream>,
83 distributor: EventDistributor,
84) {
85 loop {
86 match events.recv().await {
87 Some(ev) => {
88 let done = matches!(ev, InterpreterOutputEvent::Ended(_));
89 distributor.publish(ev).await;
90 if done {
91 break;
92 }
93 }
94 None => break,
95 }
96 }
97 distributor.close();
99}
100
101pub type StatusTx = mpsc::Sender<SubscriptionStatus>;