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