monoloop_loop/
subscription.rs1use monoloop_contracts::InterpreterOutputEvent;
4use tokio::sync::mpsc;
5
6#[derive(Clone, Debug, PartialEq, Eq, Hash)]
8pub struct SubscriberId(String);
9
10impl SubscriberId {
11 pub fn new(value: impl Into<String>) -> Self {
13 Self(value.into())
14 }
15
16 pub fn as_str(&self) -> &str {
18 &self.0
19 }
20}
21
22#[derive(Clone, Debug, PartialEq, Eq)]
24pub enum SubscriptionStatus {
25 Opened,
27 Closing,
29 Gap(SubscriptionGap),
31 Lost,
33}
34
35#[derive(Clone, Debug, PartialEq, Eq)]
37pub struct SubscriptionGap {
38 pub expected: u64,
40 pub observed: Option<u64>,
42}
43
44#[derive(Clone, Debug)]
46pub struct DeliveredEvent {
47 pub delivery_sequence: u64,
49 pub event: InterpreterOutputEvent,
51}
52
53pub struct CanonicalEventSubscription {
55 pub subscriber_id: SubscriberId,
57 rx: mpsc::Receiver<Result<DeliveredEvent, SubscriptionStatus>>,
58}
59
60impl CanonicalEventSubscription {
61 pub fn new(
63 subscriber_id: SubscriberId,
64 rx: mpsc::Receiver<Result<DeliveredEvent, SubscriptionStatus>>,
65 ) -> Self {
66 Self { subscriber_id, rx }
67 }
68
69 pub async fn recv(&mut self) -> Option<Result<DeliveredEvent, SubscriptionStatus>> {
71 self.rx.recv().await
72 }
73}
74
75#[derive(Clone)]
77pub struct SubscriptionPublisher {
78 tx: mpsc::Sender<Result<DeliveredEvent, SubscriptionStatus>>,
79 next_seq: std::sync::Arc<std::sync::atomic::AtomicU64>,
80}
81
82impl SubscriptionPublisher {
83 pub fn channel(
85 subscriber_id: impl Into<String>,
86 capacity: usize,
87 ) -> (Self, CanonicalEventSubscription) {
88 let (tx, rx) = mpsc::channel(capacity.max(1));
89 (
90 Self {
91 tx,
92 next_seq: std::sync::Arc::new(std::sync::atomic::AtomicU64::new(1)),
93 },
94 CanonicalEventSubscription::new(SubscriberId::new(subscriber_id), rx),
95 )
96 }
97
98 pub async fn publish(
100 &self,
101 event: InterpreterOutputEvent,
102 ) -> Result<(), mpsc::error::SendError<Result<DeliveredEvent, SubscriptionStatus>>> {
103 let seq = self
104 .next_seq
105 .fetch_add(1, std::sync::atomic::Ordering::SeqCst);
106 self.tx
107 .send(Ok(DeliveredEvent {
108 delivery_sequence: seq,
109 event,
110 }))
111 .await
112 }
113
114 pub async fn signal_gap(&self, expected: u64, observed: Option<u64>) -> Result<(), ()> {
116 self.tx
117 .send(Err(SubscriptionStatus::Gap(SubscriptionGap {
118 expected,
119 observed,
120 })))
121 .await
122 .map_err(|_| ())
123 }
124
125 pub async fn signal_lost(&self) -> Result<(), ()> {
127 self.tx
128 .send(Err(SubscriptionStatus::Lost))
129 .await
130 .map_err(|_| ())
131 }
132}