arminius_lib_nats/
subscriber.rs1use std::{ops::Deref, pin::Pin};
9
10use arminius_lib_message_bus::{Error, Event, ReceivedEvent, Subscriber};
11use async_nats::jetstream;
12use futures::{Stream, StreamExt as _};
13
14use crate::{
15 NatsClient, client::event_subjects, opentelemetry::extract_otel_context,
16 resubscribe::resubscribing_stream,
17};
18
19pub struct NatsReceivedEvent<E> {
24 event: E,
26 message: jetstream::Message,
28 context: opentelemetry::Context,
30}
31
32impl<E: std::fmt::Debug> std::fmt::Debug for NatsReceivedEvent<E> {
33 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
34 f.debug_struct("NatsReceivedEvent").field("event", &self.event).finish_non_exhaustive()
35 }
36}
37
38impl<E> Deref for NatsReceivedEvent<E> {
39 type Target = E;
40
41 fn deref(&self) -> &E {
42 &self.event
43 }
44}
45
46impl<E: Event> ReceivedEvent<E> for NatsReceivedEvent<E> {
47 async fn ack(&self) -> Result<(), Error> {
48 self.message.ack().await.map_err(|error| Error::AckFailed { error: error.to_string() })
49 }
50
51 fn context(&self) -> &opentelemetry::Context {
52 &self.context
53 }
54}
55
56impl NatsClient {
57 async fn subscribe_inner<E: Event + 'static>(
63 &self,
64 ) -> Result<Pin<Box<dyn Stream<Item = Result<NatsReceivedEvent<E>, Error>> + Send>>, Error> {
65 let subject = E::SUBJECT.to_owned();
66 let sub_err = |error: String| Error::SubscriptionFailed { subject: subject.clone(), error };
67
68 let stream =
69 self.ensure_event_stream::<E>().await.map_err(|error| sub_err(error.to_string()))?;
70
71 let consumer_config = self
73 .stream_config
74 .consumer
75 .pull_config(self.service_name.clone(), event_subjects::<E>());
76
77 let consumer = stream
78 .create_consumer(consumer_config)
79 .await
80 .map_err(|error| sub_err(error.to_string()))?;
81
82 let message_stream =
83 consumer.messages().await.map_err(|error| sub_err(error.to_string()))?;
84
85 Ok(Box::pin(message_stream.map(|result| {
86 let msg = result.map_err(|error| Error::ReceptionFailed {
87 subject: E::SUBJECT.to_owned(),
88 error: error.to_string(),
89 })?;
90 let context = extract_otel_context(&msg);
91 let event = E::from_payload(&msg.subject, &msg.payload).map_err(|error| {
92 Error::ReceptionFailed { subject: E::SUBJECT.to_owned(), error: error.to_string() }
93 })?;
94 Ok(NatsReceivedEvent { event, message: msg, context })
95 })))
96 }
97}
98
99impl Subscriber for NatsClient {
100 async fn subscribe<E: Event + 'static>(
112 &self,
113 ) -> Result<
114 impl Stream<Item = Result<impl ReceivedEvent<E> + Send + Sync + 'static, Error>>
115 + Send
116 + 'static,
117 Error,
118 > {
119 let initial = self.subscribe_inner::<E>().await?;
122 tracing::debug!(subject = E::SUBJECT, "Subscribed to stream");
123
124 let client = self.clone();
125 Ok(resubscribing_stream(
126 self.signals.clone(),
127 self.internal_channel_size(),
128 E::SUBJECT,
129 initial,
130 move || {
131 let client = client.clone();
132 async move { client.subscribe_inner::<E>().await }
133 },
134 ))
135 }
136}