1use crate::utils::AsyncJoinOnDrop;
18use anyhow::anyhow;
19use async_nats::{
20 Client, ConnectOptions, HeaderMap, HeaderValue, Message, PublishError, RequestError,
21 RequestErrorKind, Subject, SubscribeError, Subscriber, ToServerAddrs,
22};
23use backon::{BackoffBuilder, ExponentialBuilder};
24use futures::channel::mpsc;
25use futures::stream::FuturesUnordered;
26use futures::{FutureExt, Stream, StreamExt, select};
27use parity_scale_codec::{Decode, Encode, decode_from_bytes};
28use std::any::type_name;
29use std::collections::VecDeque;
30use std::fmt;
31use std::future::Future;
32use std::marker::PhantomData;
33use std::ops::Deref;
34use std::pin::Pin;
35use std::task::{Context, Poll};
36use std::time::Duration;
37use thiserror::Error;
38use tracing::{Instrument, debug, error, trace, warn};
39use triomphe::Arc;
40use ulid::Ulid;
41
42const EXPECTED_MESSAGE_SIZE: usize = 2 * 1024 * 1024;
43const ACKNOWLEDGEMENT_TIMEOUT: Duration = Duration::from_mins(1);
44const REQUEST_TIMEOUT: Duration = Duration::from_mins(5);
47
48pub trait GenericRequest: Encode + Decode + fmt::Debug + Send + Sync + 'static {
54 const SUBJECT: &'static str;
56 type Response: Encode + Decode + fmt::Debug + Send + Sync + 'static;
58}
59
60pub trait GenericStreamRequest: Encode + Decode + fmt::Debug + Send + Sync + 'static {
67 const SUBJECT: &'static str;
69 type Response: Encode + Decode + fmt::Debug + Send + Sync + 'static;
75}
76
77#[derive(Debug, Encode, Decode)]
81enum GenericStreamResponses<Response> {
82 Continue {
84 index: u32,
86 responses: VecDeque<Response>,
88 ack_subject: String,
91 },
92 Last {
94 index: u32,
96 responses: VecDeque<Response>,
98 },
99}
100
101impl<Response> From<GenericStreamResponses<Response>> for VecDeque<Response> {
102 #[inline]
103 fn from(value: GenericStreamResponses<Response>) -> Self {
104 #[expect(
105 clippy::rest_pattern_accessible_field,
106 reason = "Do not need other fields"
107 )]
108 match value {
109 GenericStreamResponses::Continue { responses, .. } => responses,
110 GenericStreamResponses::Last { responses, .. } => responses,
111 }
112 }
113}
114
115impl<Response> GenericStreamResponses<Response> {
116 fn next(&mut self) -> Option<Response> {
117 #[expect(
118 clippy::rest_pattern_accessible_field,
119 reason = "Do not need other fields"
120 )]
121 match self {
122 GenericStreamResponses::Continue { responses, .. } => responses.pop_front(),
123 GenericStreamResponses::Last { responses, .. } => responses.pop_front(),
124 }
125 }
126
127 fn index(&self) -> u32 {
128 #[expect(
129 clippy::rest_pattern_accessible_field,
130 reason = "Do not need other fields"
131 )]
132 match self {
133 GenericStreamResponses::Continue { index, .. } => *index,
134 GenericStreamResponses::Last { index, .. } => *index,
135 }
136 }
137
138 fn ack_subject(&self) -> Option<&str> {
139 #[expect(
140 clippy::rest_pattern_accessible_field,
141 reason = "Do not need other fields"
142 )]
143 if let GenericStreamResponses::Continue { ack_subject, .. } = self {
144 Some(ack_subject)
145 } else {
146 None
147 }
148 }
149
150 #[expect(
151 clippy::rest_pattern_accessible_field,
152 reason = "Do not care about fields"
153 )]
154 fn is_last(&self) -> bool {
155 matches!(self, Self::Last { .. })
156 }
157}
158
159#[derive(Debug, Error)]
161pub enum StreamRequestError {
162 #[error("Subscribe error: {0}")]
164 Subscribe(#[from] SubscribeError),
165 #[error("Publish error: {0}")]
167 Publish(#[from] PublishError),
168}
169
170#[derive(Debug)]
173#[pin_project::pin_project]
174pub struct StreamResponseSubscriber<Response> {
175 #[pin]
176 subscriber: Subscriber,
177 response_subject: String,
178 buffered_responses: Option<GenericStreamResponses<Response>>,
179 next_index: u32,
180 acknowledgement_sender: mpsc::UnboundedSender<(String, u32)>,
181 _background_task: AsyncJoinOnDrop<()>,
182 _phantom: PhantomData<Response>,
183}
184
185impl<Response> Stream for StreamResponseSubscriber<Response>
186where
187 Response: Decode,
188{
189 type Item = Response;
190
191 fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
192 if let Some(buffered_responses) = self.buffered_responses.as_mut() {
193 if let Some(response) = buffered_responses.next() {
194 return Poll::Ready(Some(response));
195 } else if buffered_responses.is_last() {
196 return Poll::Ready(None);
197 }
198
199 self.buffered_responses.take();
200 self.next_index += 1;
201 }
202
203 let mut projected = self.project();
204 match projected.subscriber.poll_next_unpin(cx) {
205 Poll::Ready(Some(message)) => {
206 match decode_from_bytes::<GenericStreamResponses<Response>>(message.payload.clone())
207 {
208 Ok(mut responses) => {
209 if responses.index() != *projected.next_index {
210 warn!(
211 actual_index = %responses.index(),
212 expected_index = %*projected.next_index,
213 message_type = %type_name::<Response>(),
214 response_subject = %projected.response_subject,
215 "Received unexpected response stream index, aborting stream"
216 );
217
218 return Poll::Ready(None);
219 }
220
221 if let Some(ack_subject) = responses.ack_subject() {
222 let index = responses.index();
223 let ack_subject = ack_subject.to_string();
224
225 if let Err(error) = projected
226 .acknowledgement_sender
227 .unbounded_send((ack_subject.clone(), index))
228 {
229 warn!(
230 %error,
231 %index,
232 message_type = %type_name::<Response>(),
233 response_subject = %projected.response_subject,
234 %ack_subject,
235 "Failed to send acknowledgement for stream response"
236 );
237 }
238 }
239
240 if let Some(response) = responses.next() {
241 *projected.buffered_responses = Some(responses);
242 Poll::Ready(Some(response))
243 } else {
244 Poll::Ready(None)
245 }
246 }
247 Err(error) => {
248 warn!(
249 %error,
250 response_type = %type_name::<Response>(),
251 response_subject = %projected.response_subject,
252 message = %hex::encode(message.payload),
253 "Failed to decode stream response"
254 );
255
256 Poll::Ready(None)
257 }
258 }
259 }
260 Poll::Ready(None) => Poll::Ready(None),
261 Poll::Pending => Poll::Pending,
262 }
263 }
264}
265
266impl<Response> StreamResponseSubscriber<Response> {
267 fn new(subscriber: Subscriber, response_subject: String, nats_client: NatsClient) -> Self {
268 let (acknowledgement_sender, mut acknowledgement_receiver) =
269 mpsc::unbounded::<(String, u32)>();
270
271 let ack_publisher_fut = {
272 let response_subject = response_subject.clone();
273
274 async move {
275 while let Some((subject, index)) = acknowledgement_receiver.next().await {
276 trace!(
277 %subject,
278 %index,
279 %response_subject,
280 %index,
281 "Sending stream response acknowledgement"
282 );
283 if let Err(error) = nats_client
284 .publish(subject.clone(), index.to_le_bytes().to_vec().into())
285 .await
286 {
287 warn!(
288 %error,
289 %subject,
290 %index,
291 %response_subject,
292 %index,
293 "Failed to send stream response acknowledgement"
294 );
295 return;
296 }
297 }
298 }
299 };
300 let background_task =
301 AsyncJoinOnDrop::new(tokio::spawn(ack_publisher_fut.in_current_span()), true);
302
303 Self {
304 response_subject,
305 subscriber,
306 buffered_responses: None,
307 next_index: 0,
308 acknowledgement_sender,
309 _background_task: background_task,
310 _phantom: PhantomData,
311 }
312 }
313}
314
315pub trait GenericNotification: Encode + Decode + fmt::Debug + Send + Sync + 'static {
317 const SUBJECT: &'static str;
320}
321
322pub trait GenericBroadcast: Encode + Decode + fmt::Debug + Send + Sync + 'static {
328 const SUBJECT: &'static str;
330
331 fn deterministic_message_id(&self) -> Option<HeaderValue> {
334 None
335 }
336}
337
338#[derive(Debug)]
340#[pin_project::pin_project]
341pub struct SubscriberWrapper<Message> {
342 #[pin]
343 subscriber: Subscriber,
344 _phantom: PhantomData<Message>,
345}
346
347impl<Message> Stream for SubscriberWrapper<Message>
348where
349 Message: Decode,
350{
351 type Item = Message;
352
353 fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
354 match self.project().subscriber.poll_next_unpin(cx) {
355 Poll::Ready(Some(message)) => {
356 match decode_from_bytes::<Message>(message.payload.clone()) {
357 Ok(message) => Poll::Ready(Some(message)),
358 Err(error) => {
359 warn!(
360 %error,
361 message_type = %type_name::<Message>(),
362 message = %hex::encode(message.payload),
363 "Failed to decode stream message"
364 );
365
366 Poll::Pending
367 }
368 }
369 }
370 Poll::Ready(None) => Poll::Ready(None),
371 Poll::Pending => Poll::Pending,
372 }
373 }
374}
375
376#[derive(Debug)]
377struct Inner {
378 client: Client,
379 request_retry_backoff_policy: ExponentialBuilder,
380 approximate_max_message_size: usize,
381 max_message_size: usize,
382}
383
384#[derive(Debug, Clone)]
386pub struct NatsClient {
387 inner: Arc<Inner>,
388}
389
390impl Deref for NatsClient {
391 type Target = Client;
392
393 #[inline]
394 fn deref(&self) -> &Self::Target {
395 &self.inner.client
396 }
397}
398
399impl NatsClient {
400 pub async fn new<A>(
402 addrs: A,
403 request_retry_backoff_policy: ExponentialBuilder,
404 ) -> Result<Self, async_nats::Error>
405 where
406 A: ToServerAddrs,
407 {
408 let servers = addrs.to_server_addrs()?.collect::<Vec<_>>();
409 Self::from_client(
410 async_nats::connect_with_options(
411 &servers,
412 ConnectOptions::default().request_timeout(Some(REQUEST_TIMEOUT)),
413 )
414 .await?,
415 request_retry_backoff_policy,
416 )
417 }
418
419 pub fn from_client(
421 client: Client,
422 request_retry_backoff_policy: ExponentialBuilder,
423 ) -> Result<Self, async_nats::Error> {
424 let max_payload = client.server_info().max_payload;
425 if max_payload < EXPECTED_MESSAGE_SIZE {
426 return Err(format!(
427 "Max payload {max_payload} is smaller than expected {EXPECTED_MESSAGE_SIZE}, \
428 increase it by specifying max_payload = 2MB or higher number in NATS configuration"
429 )
430 .into());
431 }
432
433 let inner = Inner {
434 client,
435 request_retry_backoff_policy,
436 approximate_max_message_size: max_payload * 9 / 10,
438 max_message_size: max_payload,
440 };
441
442 Ok(Self {
443 inner: Arc::new(inner),
444 })
445 }
446
447 pub fn approximate_max_message_size(&self) -> usize {
450 self.inner.approximate_max_message_size
451 }
452
453 pub async fn request<Request>(
455 &self,
456 request: &Request,
457 instance: Option<&str>,
458 ) -> Result<Request::Response, RequestError>
459 where
460 Request: GenericRequest,
461 {
462 let subject = subject_with_instance(Request::SUBJECT, instance);
463 let mut maybe_retry_backoff = None;
464 let message = loop {
465 match self
466 .inner
467 .client
468 .request(subject.clone(), request.encode().into())
469 .await
470 {
471 Ok(message) => {
472 break message;
473 }
474 Err(error) => {
475 match error.kind() {
476 RequestErrorKind::TimedOut | RequestErrorKind::NoResponders => {
477 }
479 RequestErrorKind::InvalidSubject
480 | RequestErrorKind::MaxPayloadExceeded
481 | RequestErrorKind::Other => {
482 return Err(error);
483 }
484 }
485
486 let retry_backoff = maybe_retry_backoff
487 .get_or_insert_with(|| self.inner.request_retry_backoff_policy.build());
488
489 if let Some(delay) = retry_backoff.next() {
490 debug!(
491 %subject,
492 %error,
493 request_type = %type_name::<Request>(),
494 ?delay,
495 "Failed to make request, retrying after some delay"
496 );
497
498 tokio::time::sleep(delay).await;
499 } else {
500 return Err(error);
501 }
502 }
503 }
504 };
505
506 let response =
507 decode_from_bytes::<Request::Response>(message.payload.clone()).map_err(|error| {
508 warn!(
509 %subject,
510 %error,
511 response_type = %type_name::<Request::Response>(),
512 response = %hex::encode(message.payload),
513 "Response decoding failed"
514 );
515
516 RequestErrorKind::Other
517 })?;
518
519 Ok(response)
520 }
521
522 pub async fn request_responder<Request, F, OP>(
537 &self,
538 instance: Option<&str>,
539 queue_group: Option<String>,
540 process: OP,
541 ) -> anyhow::Result<()>
542 where
543 Request: GenericRequest,
544 F: Future<Output = Option<Request::Response>> + Send,
545 OP: Fn(Request) -> F + Send + Sync,
546 {
547 let mut processing = FuturesUnordered::new();
549
550 let subscription = self
551 .common_subscribe(Request::SUBJECT, instance, queue_group)
552 .await
553 .map_err(|error| {
554 anyhow!(
555 "Failed to subscribe to {} requests for {instance:?}: {error}",
556 type_name::<Request>(),
557 )
558 })?;
559
560 debug!(
561 request_type = %type_name::<Request>(),
562 ?subscription,
563 "Requests subscription"
564 );
565 let mut subscription = subscription.fuse();
566
567 loop {
568 select! {
569 message = subscription.select_next_some() => {
570 processing.push(
572 self
573 .process_request(
574 message,
575 &process,
576 )
577 .in_current_span(),
578 );
579 },
580 _ = processing.next() => {
581 },
583 complete => {
584 break;
585 }
586 }
587 }
588
589 Ok(())
590 }
591
592 async fn process_request<Request, F, OP>(&self, message: Message, process: OP)
593 where
594 Request: GenericRequest,
595 F: Future<Output = Option<Request::Response>> + Send,
596 OP: Fn(Request) -> F + Send + Sync,
597 {
598 let Some(reply_subject) = message.reply else {
599 return;
600 };
601
602 let message_payload_size = message.payload.len();
603 let request = match decode_from_bytes::<Request>(message.payload.clone()) {
604 Ok(request) => {
605 drop(message.payload);
607 request
608 }
609 Err(error) => {
610 warn!(
611 request_type = %type_name::<Request>(),
612 %error,
613 message = %hex::encode(message.payload),
614 "Failed to decode request"
615 );
616 return;
617 }
618 };
619
620 if message_payload_size > 1024 {
622 trace!(
623 request_type = %type_name::<Request>(),
624 %reply_subject,
625 "Processing request"
626 );
627 } else {
628 trace!(
629 request_type = %type_name::<Request>(),
630 ?request,
631 %reply_subject,
632 "Processing request"
633 );
634 }
635
636 if let Some(response) = process(request).await
637 && let Err(error) = self.publish(reply_subject, response.encode().into()).await
638 {
639 warn!(
640 request_type = %type_name::<Request>(),
641 %error,
642 "Failed to send response"
643 );
644 }
645 }
646
647 pub async fn stream_request<Request>(
649 &self,
650 request: &Request,
651 instance: Option<&str>,
652 ) -> Result<StreamResponseSubscriber<Request::Response>, StreamRequestError>
653 where
654 Request: GenericStreamRequest,
655 {
656 let stream_request_subject = subject_with_instance(Request::SUBJECT, instance);
657 let stream_response_subject = format!("stream-response.{}", Ulid::generate());
658
659 let subscriber = self
660 .inner
661 .client
662 .subscribe(stream_response_subject.clone())
663 .await?;
664
665 debug!(
666 request_type = %type_name::<Request>(),
667 %stream_request_subject,
668 %stream_response_subject,
669 ?subscriber,
670 "Stream request subscription"
671 );
672
673 self.inner
674 .client
675 .publish_with_reply(
676 stream_request_subject,
677 stream_response_subject.clone(),
678 request.encode().into(),
679 )
680 .await?;
681
682 Ok(StreamResponseSubscriber::new(
683 subscriber,
684 stream_response_subject,
685 self.clone(),
686 ))
687 }
688
689 pub async fn stream_request_responder<Request, F, S, OP>(
704 &self,
705 instance: Option<&str>,
706 queue_group: Option<String>,
707 process: OP,
708 ) -> anyhow::Result<()>
709 where
710 Request: GenericStreamRequest,
711 F: Future<Output = Option<S>> + Send,
712 S: Stream<Item = Request::Response> + Unpin,
713 OP: Fn(Request) -> F + Send + Sync,
714 {
715 let mut processing = FuturesUnordered::new();
717
718 let subscription = self
719 .common_subscribe(Request::SUBJECT, instance, queue_group)
720 .await
721 .map_err(|error| {
722 anyhow!(
723 "Failed to subscribe to {} stream requests for {instance:?}: {error}",
724 type_name::<Request>(),
725 )
726 })?;
727
728 debug!(
729 request_type = %type_name::<Request>(),
730 ?subscription,
731 "Stream requests subscription"
732 );
733 let mut subscription = subscription.fuse();
734
735 loop {
736 select! {
737 message = subscription.select_next_some() => {
738 processing.push(
740 self
741 .process_stream_request(
742 message,
743 &process,
744 )
745 .in_current_span(),
746 );
747 },
748 _ = processing.next() => {
749 },
751 complete => {
752 break;
753 }
754 }
755 }
756
757 Ok(())
758 }
759
760 async fn process_stream_request<Request, F, S, OP>(&self, message: Message, process: OP)
761 where
762 Request: GenericStreamRequest,
763 F: Future<Output = Option<S>> + Send,
764 S: Stream<Item = Request::Response> + Unpin,
765 OP: Fn(Request) -> F + Send + Sync,
766 {
767 let Some(reply_subject) = message.reply else {
768 return;
769 };
770
771 let message_payload_size = message.payload.len();
772 let request = match decode_from_bytes::<Request>(message.payload.clone()) {
773 Ok(request) => {
774 drop(message.payload);
776 request
777 }
778 Err(error) => {
779 warn!(
780 request_type = %type_name::<Request>(),
781 %error,
782 message = %hex::encode(message.payload),
783 "Failed to decode request"
784 );
785 return;
786 }
787 };
788
789 if message_payload_size > 1024 {
791 trace!(
792 request_type = %type_name::<Request>(),
793 %reply_subject,
794 "Processing request"
795 );
796 } else {
797 trace!(
798 request_type = %type_name::<Request>(),
799 ?request,
800 %reply_subject,
801 "Processing request"
802 );
803 }
804
805 if let Some(stream) = process(request).await {
806 self.stream_response::<Request, _>(reply_subject, stream)
807 .await;
808 }
809 }
810
811 async fn stream_response<Request, S>(&self, response_subject: Subject, response_stream: S)
813 where
814 Request: GenericStreamRequest,
815 S: Stream<Item = Request::Response> + Unpin,
816 {
817 type Response<Request> =
818 GenericStreamResponses<<Request as GenericStreamRequest>::Response>;
819
820 let mut response_stream = response_stream.fuse();
821
822 let Some(first_element) = response_stream.next().await else {
824 if let Err(error) = self
825 .publish(
826 response_subject.clone(),
827 Response::<Request>::Last {
828 index: 0,
829 responses: VecDeque::new(),
830 }
831 .encode()
832 .into(),
833 )
834 .await
835 {
836 warn!(
837 %response_subject,
838 %error,
839 request_type = %type_name::<Request>(),
840 response_type = %type_name::<Request::Response>(),
841 "Failed to send stream response"
842 );
843 }
844
845 return;
846 };
847 let max_message_size = self.inner.max_message_size;
848 let approximate_max_message_size = self.approximate_max_message_size();
849 let max_responses_per_message = approximate_max_message_size / first_element.encoded_size();
850
851 let ack_subject = format!("stream-response-ack.{}", Ulid::generate());
852 let mut ack_subscription = match self.subscribe(ack_subject.clone()).await {
853 Ok(ack_subscription) => ack_subscription,
854 Err(error) => {
855 warn!(
856 %response_subject,
857 %error,
858 request_type = %type_name::<Request>(),
859 response_type = %type_name::<Request::Response>(),
860 "Failed to subscribe to ack subject"
861 );
862 return;
863 }
864 };
865 debug!(
866 %response_subject,
867 request_type = %type_name::<Request>(),
868 response_type = %type_name::<Request::Response>(),
869 ?ack_subscription,
870 "Ack subscription subscription"
871 );
872 let mut index = 0;
873 let mut buffer = VecDeque::with_capacity(max_responses_per_message);
875 buffer.push_back(first_element);
876 let mut overflow_buffer = VecDeque::new();
877
878 loop {
879 if buffer.is_empty()
881 && let Some(element) = response_stream.next().await
882 {
883 buffer.push_back(element);
884 }
885 let mut buffer_encoded_size = buffer.encoded_size();
889 while buffer_encoded_size < approximate_max_message_size
890 && let Some(element) = response_stream.next().now_or_never().flatten()
891 {
892 buffer_encoded_size += element.encoded_size();
893 buffer.push_back(element);
894 }
895
896 loop {
897 let is_done = response_stream.is_done() && overflow_buffer.is_empty();
898 let num_messages = buffer.len();
899 let response = if is_done {
900 Response::<Request>::Last {
901 index,
902 responses: buffer,
903 }
904 } else {
905 Response::<Request>::Continue {
906 index,
907 responses: buffer,
908 ack_subject: ack_subject.clone(),
909 }
910 };
911 let encoded_response = response.encode();
912 let encoded_response_len = encoded_response.len();
913 if encoded_response_len > max_message_size {
916 buffer = response.into();
917 if let Some(element) = buffer.pop_back() {
918 if buffer.is_empty() {
919 error!(
920 ?element,
921 encoded_response_len,
922 max_message_size,
923 "Element was too large to fit into NATS message, this is an \
924 implementation bug"
925 );
926 }
927 overflow_buffer.push_front(element);
928 continue;
929 }
930
931 error!(
932 %response_subject,
933 request_type = %type_name::<Request>(),
934 response_type = %type_name::<Request::Response>(),
935 "Empty response overflown message size, this should never happen"
936 );
937 return;
938 }
939
940 debug!(
941 %response_subject,
942 num_messages,
943 %index,
944 %is_done,
945 "Publishing stream response messages",
946 );
947
948 if let Err(error) = self
949 .publish(response_subject.clone(), encoded_response.into())
950 .await
951 {
952 warn!(
953 %response_subject,
954 %error,
955 request_type = %type_name::<Request>(),
956 response_type = %type_name::<Request::Response>(),
957 "Failed to send stream response"
958 );
959 return;
960 }
961
962 if is_done {
963 return;
964 }
965
966 buffer = response.into();
967 buffer.clear();
968 buffer.append(&mut overflow_buffer);
970
971 if index >= 1 {
972 let expected_index = index - 1;
974
975 trace!(
976 %response_subject,
977 %expected_index,
978 "Waiting for acknowledgement"
979 );
980 match tokio::time::timeout(ACKNOWLEDGEMENT_TIMEOUT, ack_subscription.next())
981 .await
982 {
983 Ok(Some(message)) => {
984 if let Some(received_index) =
985 message.payload.get(..size_of::<u32>()).map(|bytes| {
986 u32::from_le_bytes(
987 bytes.try_into().expect("Correctly chunked slice; qed"),
988 )
989 })
990 {
991 debug!(
992 %response_subject,
993 %received_index,
994 "Received acknowledgement"
995 );
996 if received_index != expected_index {
997 warn!(
998 %response_subject,
999 %received_index,
1000 %expected_index,
1001 request_type = %type_name::<Request>(),
1002 response_type = %type_name::<Request::Response>(),
1003 message = %hex::encode(message.payload),
1004 "Unexpected acknowledgement index"
1005 );
1006 return;
1007 }
1008 } else {
1009 warn!(
1010 %response_subject,
1011 request_type = %type_name::<Request>(),
1012 response_type = %type_name::<Request::Response>(),
1013 message = %hex::encode(message.payload),
1014 "Unexpected acknowledgement message"
1015 );
1016 return;
1017 }
1018 }
1019 Ok(None) => {
1020 warn!(
1021 %response_subject,
1022 request_type = %type_name::<Request>(),
1023 response_type = %type_name::<Request::Response>(),
1024 "Acknowledgement stream ended unexpectedly"
1025 );
1026 return;
1027 }
1028 Err(_error) => {
1029 warn!(
1030 %response_subject,
1031 %expected_index,
1032 request_type = %type_name::<Request>(),
1033 response_type = %type_name::<Request::Response>(),
1034 "Acknowledgement wait timed out"
1035 );
1036 return;
1037 }
1038 }
1039 }
1040
1041 index += 1;
1042
1043 if buffer.is_empty() {
1045 break;
1046 }
1047 }
1048 }
1049 }
1050
1051 pub async fn notification<Notification>(
1053 &self,
1054 notification: &Notification,
1055 instance: Option<&str>,
1056 ) -> Result<(), PublishError>
1057 where
1058 Notification: GenericNotification,
1059 {
1060 self.inner
1061 .client
1062 .publish(
1063 subject_with_instance(Notification::SUBJECT, instance),
1064 notification.encode().into(),
1065 )
1066 .await
1067 }
1068
1069 pub async fn broadcast<Broadcast>(
1071 &self,
1072 message: &Broadcast,
1073 instance: &str,
1074 ) -> Result<(), PublishError>
1075 where
1076 Broadcast: GenericBroadcast,
1077 {
1078 self.inner
1079 .client
1080 .publish_with_headers(
1081 Broadcast::SUBJECT.replace('*', instance),
1082 {
1083 let mut headers = HeaderMap::new();
1084 if let Some(message_id) = message.deterministic_message_id() {
1085 headers.insert("Nats-Msg-Id", message_id);
1086 }
1087 headers
1088 },
1089 message.encode().into(),
1090 )
1091 .await
1092 }
1093
1094 pub async fn subscribe_to_notifications<Notification>(
1097 &self,
1098 instance: Option<&str>,
1099 queue_group: Option<String>,
1100 ) -> Result<SubscriberWrapper<Notification>, SubscribeError>
1101 where
1102 Notification: GenericNotification,
1103 {
1104 self.simple_subscribe(Notification::SUBJECT, instance, queue_group)
1105 .await
1106 }
1107
1108 pub async fn subscribe_to_broadcasts<Broadcast>(
1111 &self,
1112 instance: Option<&str>,
1113 queue_group: Option<String>,
1114 ) -> Result<SubscriberWrapper<Broadcast>, SubscribeError>
1115 where
1116 Broadcast: GenericBroadcast,
1117 {
1118 self.simple_subscribe(Broadcast::SUBJECT, instance, queue_group)
1119 .await
1120 }
1121
1122 async fn simple_subscribe<Message>(
1125 &self,
1126 subject: &'static str,
1127 instance: Option<&str>,
1128 queue_group: Option<String>,
1129 ) -> Result<SubscriberWrapper<Message>, SubscribeError>
1130 where
1131 Message: Decode,
1132 {
1133 let subscriber = self
1134 .common_subscribe(subject, instance, queue_group)
1135 .await?;
1136 debug!(
1137 %subject,
1138 message_type = %type_name::<Message>(),
1139 ?subscriber,
1140 "Simple subscription"
1141 );
1142
1143 Ok(SubscriberWrapper {
1144 subscriber,
1145 _phantom: PhantomData,
1146 })
1147 }
1148
1149 async fn common_subscribe(
1152 &self,
1153 subject: &'static str,
1154 instance: Option<&str>,
1155 queue_group: Option<String>,
1156 ) -> Result<Subscriber, SubscribeError> {
1157 let subscriber = if let Some(queue_group) = queue_group {
1158 self.inner
1159 .client
1160 .queue_subscribe(subject_with_instance(subject, instance), queue_group)
1161 .await?
1162 } else {
1163 self.inner
1164 .client
1165 .subscribe(subject_with_instance(subject, instance))
1166 .await?
1167 };
1168
1169 Ok(subscriber)
1170 }
1171}
1172
1173fn subject_with_instance(subject: &'static str, instance: Option<&str>) -> Subject {
1174 if let Some(instance) = instance {
1175 Subject::from(subject.replace('*', instance))
1176 } else {
1177 Subject::from_static(subject)
1178 }
1179}