Skip to main content

async_nats/jetstream/
stream.rs

1// Copyright 2020-2022 The NATS Authors
2// Licensed under the Apache License, Version 2.0 (the "License");
3// you may not use this file except in compliance with the License.
4// You may obtain a copy of the License at
5//
6// http://www.apache.org/licenses/LICENSE-2.0
7//
8// Unless required by applicable law or agreed to in writing, software
9// distributed under the License is distributed on an "AS IS" BASIS,
10// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11// See the License for the specific language governing permissions and
12// limitations under the License.
13//
14//! Manage operations on a [Stream], create/delete/update [Consumer].
15
16use std::{
17    collections::{self, HashMap},
18    fmt::{self, Debug, Display},
19    future::IntoFuture,
20    io::{self},
21    pin::Pin,
22    str::FromStr,
23    task::Poll,
24    time::Duration,
25};
26
27use crate::datetime::{rfc3339, DateTime};
28use crate::{
29    error::Error, header::HeaderName, is_valid_subject, HeaderMap, HeaderValue, StatusCode,
30};
31use base64::engine::general_purpose::STANDARD;
32use base64::engine::Engine;
33use bytes::Bytes;
34use futures_util::{future::BoxFuture, FutureExt, TryFutureExt};
35use serde::{Deserialize, Deserializer, Serialize};
36use serde_json::json;
37
38use super::{
39    consumer::{self, Consumer, FromConsumer, IntoConsumerConfig},
40    context::{
41        ConsumerInfoError, ConsumerInfoErrorKind, RequestError, RequestErrorKind, StreamsError,
42        StreamsErrorKind,
43    },
44    errors::ErrorCode,
45    is_valid_name,
46    message::{StreamMessage, StreamMessageError},
47    response::Response,
48    Context,
49};
50
51pub type InfoError = RequestError;
52
53#[derive(Clone, Debug, PartialEq)]
54pub enum DirectGetErrorKind {
55    NotFound,
56    InvalidSubject,
57    TimedOut,
58    Request,
59    ErrorResponse(StatusCode, String),
60    Other,
61}
62
63impl Display for DirectGetErrorKind {
64    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
65        match self {
66            Self::InvalidSubject => write!(f, "invalid subject"),
67            Self::NotFound => write!(f, "message not found"),
68            Self::ErrorResponse(status, description) => {
69                write!(f, "unable to get message: {status} {description}")
70            }
71            Self::Other => write!(f, "error getting message"),
72            Self::TimedOut => write!(f, "timed out"),
73            Self::Request => write!(f, "request failed"),
74        }
75    }
76}
77
78pub type DirectGetError = Error<DirectGetErrorKind>;
79
80impl From<crate::RequestError> for DirectGetError {
81    fn from(err: crate::RequestError) -> Self {
82        match err.kind() {
83            crate::RequestErrorKind::TimedOut => DirectGetError::new(DirectGetErrorKind::TimedOut),
84            crate::RequestErrorKind::NoResponders => {
85                DirectGetError::new(DirectGetErrorKind::ErrorResponse(
86                    StatusCode::NO_RESPONDERS,
87                    "no responders".to_string(),
88                ))
89            }
90            crate::RequestErrorKind::InvalidSubject
91            | crate::RequestErrorKind::MaxPayloadExceeded
92            | crate::RequestErrorKind::Other => {
93                DirectGetError::with_source(DirectGetErrorKind::Other, err)
94            }
95        }
96    }
97}
98
99impl From<serde_json::Error> for DirectGetError {
100    fn from(err: serde_json::Error) -> Self {
101        DirectGetError::with_source(DirectGetErrorKind::Other, err)
102    }
103}
104
105impl From<StreamMessageError> for DirectGetError {
106    fn from(err: StreamMessageError) -> Self {
107        DirectGetError::with_source(DirectGetErrorKind::Other, err)
108    }
109}
110
111#[derive(Clone, Debug, PartialEq)]
112pub enum DeleteMessageErrorKind {
113    Request,
114    TimedOut,
115    JetStream(super::errors::Error),
116}
117
118impl Display for DeleteMessageErrorKind {
119    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
120        match self {
121            Self::Request => write!(f, "request failed"),
122            Self::TimedOut => write!(f, "timed out"),
123            Self::JetStream(err) => write!(f, "JetStream error: {err}"),
124        }
125    }
126}
127
128pub type DeleteMessageError = Error<DeleteMessageErrorKind>;
129
130/// Handle to operations that can be performed on a `Stream`.
131/// It's generic over the type of `info` field to allow `Stream` with or without
132/// info contents.
133#[derive(Debug, Clone)]
134pub struct Stream<T = Info> {
135    pub(crate) info: T,
136    pub(crate) context: Context,
137    pub(crate) name: String,
138}
139
140impl Stream<Info> {
141    /// Retrieves `info` about [Stream] from the server, updates the cached `info` inside
142    /// [Stream] and returns it.
143    ///
144    /// # Examples
145    ///
146    /// ```no_run
147    /// # #[tokio::main]
148    /// # async fn main() -> Result<(), async_nats::Error> {
149    /// let client = async_nats::connect("localhost:4222").await?;
150    /// let jetstream = async_nats::jetstream::new(client);
151    ///
152    /// let mut stream = jetstream.get_stream("events").await?;
153    ///
154    /// let info = stream.info().await?;
155    /// # Ok(())
156    /// # }
157    /// ```
158    pub async fn info(&mut self) -> Result<&Info, InfoError> {
159        let subject = format!("STREAM.INFO.{}", self.info.config.name);
160
161        match self.context.request(subject, &json!({})).await? {
162            Response::Ok::<Info>(info) => {
163                self.info = info;
164                Ok(&self.info)
165            }
166            Response::Err { error } => Err(error.into()),
167        }
168    }
169
170    /// Returns cached [Info] for the [Stream].
171    /// Cache is either from initial creation/retrieval of the [Stream] or last call to
172    /// [Stream::info].
173    ///
174    /// # Examples
175    ///
176    /// ```no_run
177    /// # #[tokio::main]
178    /// # async fn main() -> Result<(), async_nats::Error> {
179    /// let client = async_nats::connect("localhost:4222").await?;
180    /// let jetstream = async_nats::jetstream::new(client);
181    ///
182    /// let stream = jetstream.get_stream("events").await?;
183    ///
184    /// let info = stream.cached_info();
185    /// # Ok(())
186    /// # }
187    /// ```
188    pub fn cached_info(&self) -> &Info {
189        &self.info
190    }
191}
192
193impl<I> Stream<I> {
194    /// Retrieves `info` about [Stream] from the server. Does not update the cache.
195    /// Can be used on Stream retrieved by [Context::get_stream_no_info]
196    pub async fn get_info(&self) -> Result<Info, InfoError> {
197        let subject = format!("STREAM.INFO.{}", self.name);
198
199        match self.context.request(subject, &json!({})).await? {
200            Response::Ok::<Info>(info) => Ok(info),
201            Response::Err { error } => Err(error.into()),
202        }
203    }
204
205    /// Retrieves [[Info]] from the server and returns a [[futures_util::Stream]] that allows
206    /// iterating over all subjects in the stream fetched via paged API.
207    ///
208    /// # Examples
209    ///
210    /// ```no_run
211    /// # #[tokio::main]
212    /// # async fn main() -> Result<(), async_nats::Error> {
213    /// use futures_util::TryStreamExt;
214    /// let client = async_nats::connect("localhost:4222").await?;
215    /// let jetstream = async_nats::jetstream::new(client);
216    ///
217    /// let mut stream = jetstream.get_stream("events").await?;
218    ///
219    /// let mut info = stream.info_with_subjects("events.>").await?;
220    ///
221    /// while let Some((subject, count)) = info.try_next().await? {
222    ///     println!("Subject: {} count: {}", subject, count);
223    /// }
224    /// # Ok(())
225    /// # }
226    /// ```
227    pub async fn info_with_subjects<F: AsRef<str>>(
228        &self,
229        subjects_filter: F,
230    ) -> Result<InfoWithSubjects, InfoError> {
231        let subjects_filter = subjects_filter.as_ref().to_string();
232        // TODO: validate the subject and decide if this should be a `Subject`
233        let info = stream_info_with_details(
234            self.context.clone(),
235            self.name.clone(),
236            0,
237            false,
238            subjects_filter.clone(),
239        )
240        .await?;
241
242        Ok(InfoWithSubjects::new(
243            self.context.clone(),
244            info,
245            subjects_filter,
246        ))
247    }
248
249    /// Creates a builder that allows to customize `Stream::Info`.
250    ///
251    /// # Examples
252    /// ```no_run
253    /// # #[tokio::main]
254    /// # async fn main() -> Result<(), async_nats::Error> {
255    /// use futures_util::TryStreamExt;
256    /// let client = async_nats::connect("localhost:4222").await?;
257    /// let jetstream = async_nats::jetstream::new(client);
258    ///
259    /// let mut stream = jetstream.get_stream("events").await?;
260    ///
261    /// let mut info = stream
262    ///     .info_builder()
263    ///     .with_deleted(true)
264    ///     .subjects("events.>")
265    ///     .fetch()
266    ///     .await?;
267    ///
268    /// while let Some((subject, count)) = info.try_next().await? {
269    ///     println!("Subject: {} count: {}", subject, count);
270    /// }
271    /// # Ok(())
272    /// # }
273    /// ```
274    pub fn info_builder(&self) -> StreamInfoBuilder {
275        StreamInfoBuilder::new(self.context.clone(), self.name.clone())
276    }
277
278    /// Creates a builder for direct get operations.
279    ///
280    /// Allows for more control over direct get requests.
281    ///
282    /// # Examples
283    ///
284    /// ```no_run
285    /// # #[tokio::main]
286    /// # async fn main() -> Result<(), async_nats::Error> {
287    /// let client = async_nats::connect("demo.nats.io").await?;
288    /// let jetstream = async_nats::jetstream::new(client);
289    ///
290    /// let stream = jetstream.get_stream("events").await?;
291    ///
292    /// // Get message without headers
293    /// let message = stream.direct_get_builder().sequence(100).send().await?;
294    /// # Ok(())
295    /// # }
296    /// ```
297    pub fn direct_get_builder(&self) -> DirectGetBuilder<WithHeaders> {
298        DirectGetBuilder::new(self.context.clone(), self.name.clone())
299    }
300
301    /// Gets next message for a [Stream].
302    ///
303    /// Requires a [Stream] with `allow_direct` set to `true`.
304    /// This is different from [Stream::get_raw_message], as it can fetch [super::message::StreamMessage]
305    /// from any replica member. This means read after write is possible,
306    /// as that given replica might not yet catch up with the leader.
307    ///
308    /// # Examples
309    ///
310    /// ```no_run
311    /// # #[tokio::main]
312    /// # async fn main() -> Result<(), async_nats::Error> {
313    /// let client = async_nats::connect("demo.nats.io").await?;
314    /// let jetstream = async_nats::jetstream::new(client);
315    ///
316    /// let stream = jetstream
317    ///     .create_stream(async_nats::jetstream::stream::Config {
318    ///         name: "events".to_string(),
319    ///         subjects: vec!["events.>".to_string()],
320    ///         allow_direct: true,
321    ///         ..Default::default()
322    ///     })
323    ///     .await?;
324    ///
325    /// jetstream.publish("events.data", "data".into()).await?;
326    /// let pub_ack = jetstream.publish("events.data", "data".into()).await?;
327    ///
328    /// let message = stream
329    ///     .direct_get_next_for_subject("events.data", Some(pub_ack.await?.sequence))
330    ///     .await?;
331    ///
332    /// # Ok(())
333    /// # }
334    /// ```
335    pub async fn direct_get_next_for_subject<T: Into<String>>(
336        &self,
337        subject: T,
338        sequence: Option<u64>,
339    ) -> Result<StreamMessage, DirectGetError> {
340        let subject_str = subject.into();
341        if !is_valid_subject(&subject_str) {
342            return Err(DirectGetError::new(DirectGetErrorKind::InvalidSubject));
343        }
344
345        let mut builder = self.direct_get_builder().next_by_subject(subject_str);
346        if let Some(seq) = sequence {
347            builder = builder.sequence(seq);
348        }
349
350        builder.send().await
351    }
352
353    /// Gets first message from [Stream].
354    ///
355    /// Requires a [Stream] with `allow_direct` set to `true`.
356    /// This is different from [Stream::get_raw_message], as it can fetch [super::message::StreamMessage]
357    /// from any replica member. This means read after write is possible,
358    /// as that given replica might not yet catch up with the leader.
359    ///
360    /// # Examples
361    ///
362    /// ```no_run
363    /// # #[tokio::main]
364    /// # async fn main() -> Result<(), async_nats::Error> {
365    /// let client = async_nats::connect("demo.nats.io").await?;
366    /// let jetstream = async_nats::jetstream::new(client);
367    ///
368    /// let stream = jetstream
369    ///     .create_stream(async_nats::jetstream::stream::Config {
370    ///         name: "events".to_string(),
371    ///         subjects: vec!["events.>".to_string()],
372    ///         allow_direct: true,
373    ///         ..Default::default()
374    ///     })
375    ///     .await?;
376    ///
377    /// let pub_ack = jetstream.publish("events.data", "data".into()).await?;
378    ///
379    /// let message = stream.direct_get_first_for_subject("events.data").await?;
380    ///
381    /// # Ok(())
382    /// # }
383    /// ```
384    pub async fn direct_get_first_for_subject<T: Into<String>>(
385        &self,
386        subject: T,
387    ) -> Result<StreamMessage, DirectGetError> {
388        let subject_str = subject.into();
389        if !is_valid_subject(&subject_str) {
390            return Err(DirectGetError::new(DirectGetErrorKind::InvalidSubject));
391        }
392
393        self.direct_get_builder()
394            .next_by_subject(subject_str)
395            .send()
396            .await
397    }
398
399    /// Gets message from [Stream] with given `sequence id`.
400    ///
401    /// Requires a [Stream] with `allow_direct` set to `true`.
402    /// This is different from [Stream::get_raw_message], as it can fetch [super::message::StreamMessage]
403    /// from any replica member. This means read after write is possible,
404    /// as that given replica might not yet catch up with the leader.
405    ///
406    /// # Examples
407    ///
408    /// ```no_run
409    /// # #[tokio::main]
410    /// # async fn main() -> Result<(), async_nats::Error> {
411    /// let client = async_nats::connect("demo.nats.io").await?;
412    /// let jetstream = async_nats::jetstream::new(client);
413    ///
414    /// let stream = jetstream
415    ///     .create_stream(async_nats::jetstream::stream::Config {
416    ///         name: "events".to_string(),
417    ///         subjects: vec!["events.>".to_string()],
418    ///         allow_direct: true,
419    ///         ..Default::default()
420    ///     })
421    ///     .await?;
422    ///
423    /// let pub_ack = jetstream.publish("events.data", "data".into()).await?;
424    ///
425    /// let message = stream.direct_get(pub_ack.await?.sequence).await?;
426    ///
427    /// # Ok(())
428    /// # }
429    /// ```
430    pub async fn direct_get(&self, sequence: u64) -> Result<StreamMessage, DirectGetError> {
431        self.direct_get_builder().sequence(sequence).send().await
432    }
433
434    /// Gets last message for a given `subject`.
435    ///
436    /// Requires a [Stream] with `allow_direct` set to `true`.
437    /// This is different from [Stream::get_raw_message], as it can fetch [super::message::StreamMessage]
438    /// from any replica member. This means read after write is possible,
439    /// as that given replica might not yet catch up with the leader.
440    ///
441    /// # Examples
442    ///
443    /// ```no_run
444    /// # #[tokio::main]
445    /// # async fn main() -> Result<(), async_nats::Error> {
446    /// let client = async_nats::connect("demo.nats.io").await?;
447    /// let jetstream = async_nats::jetstream::new(client);
448    ///
449    /// let stream = jetstream
450    ///     .create_stream(async_nats::jetstream::stream::Config {
451    ///         name: "events".to_string(),
452    ///         subjects: vec!["events.>".to_string()],
453    ///         allow_direct: true,
454    ///         ..Default::default()
455    ///     })
456    ///     .await?;
457    ///
458    /// jetstream.publish("events.data", "data".into()).await?;
459    ///
460    /// let message = stream.direct_get_last_for_subject("events.data").await?;
461    ///
462    /// # Ok(())
463    /// # }
464    /// ```
465    pub async fn direct_get_last_for_subject<T: Into<String>>(
466        &self,
467        subject: T,
468    ) -> Result<StreamMessage, DirectGetError> {
469        self.direct_get_builder()
470            .last_by_subject(subject)
471            .send()
472            .await
473    }
474    /// Creates a builder for retrieving messages from the stream with flexible options.
475    /// Raw message methods retrieve messages directly from the stream leader instead
476    /// of a replica. This should be used with care, as it can put additional load on the
477    /// stream leader.
478    ///
479    /// # Examples
480    ///
481    /// ```no_run
482    /// # #[tokio::main]
483    /// # async fn main() -> Result<(), async_nats::Error> {
484    /// let client = async_nats::connect("localhost:4222").await?;
485    /// let context = async_nats::jetstream::new(client);
486    /// let stream = context.get_stream("events").await?;
487    ///
488    /// // Get message without headers
489    /// let value = stream.raw_message_builder().sequence(100).send().await?;
490    /// # Ok(())
491    /// # }
492    /// ```
493    pub fn raw_message_builder(&self) -> RawMessageBuilder<WithHeaders> {
494        RawMessageBuilder::new(self.context.clone(), self.name.clone())
495    }
496
497    /// Get a raw message from the stream for a given stream sequence.
498    /// This low-level API always reaches stream leader.
499    /// This should be discouraged in favor of using [Stream::direct_get].
500    ///
501    /// # Examples
502    ///
503    /// ```no_run
504    /// #[tokio::main]
505    /// # async fn main() -> Result<(), async_nats::Error> {
506    /// use futures_util::StreamExt;
507    /// use futures_util::TryStreamExt;
508    ///
509    /// let client = async_nats::connect("localhost:4222").await?;
510    /// let context = async_nats::jetstream::new(client);
511    ///
512    /// let stream = context
513    ///     .get_or_create_stream(async_nats::jetstream::stream::Config {
514    ///         name: "events".to_string(),
515    ///         max_messages: 10_000,
516    ///         ..Default::default()
517    ///     })
518    ///     .await?;
519    ///
520    /// let publish_ack = context.publish("events", "data".into()).await?;
521    /// let raw_message = stream.get_raw_message(publish_ack.await?.sequence).await?;
522    /// println!("Retrieved raw message {:?}", raw_message);
523    /// # Ok(())
524    /// # }
525    /// ```
526    pub async fn get_raw_message(&self, sequence: u64) -> Result<StreamMessage, RawMessageError> {
527        self.raw_message_builder().sequence(sequence).send().await
528    }
529
530    /// Get a first message from the stream for a given subject starting from provided sequence.
531    /// This low-level API always reaches stream leader.
532    /// This should be discouraged in favor of using [Stream::direct_get_first_for_subject].
533    ///
534    /// # Examples
535    ///
536    /// ```no_run
537    /// #[tokio::main]
538    /// # async fn main() -> Result<(), async_nats::Error> {
539    /// use futures_util::StreamExt;
540    /// use futures_util::TryStreamExt;
541    ///
542    /// let client = async_nats::connect("localhost:4222").await?;
543    /// let context = async_nats::jetstream::new(client);
544    /// let stream = context.get_stream_no_info("events").await?;
545    ///
546    /// let raw_message = stream
547    ///     .get_first_raw_message_by_subject("events.created", 10)
548    ///     .await?;
549    /// println!("Retrieved raw message {:?}", raw_message);
550    /// # Ok(())
551    /// # }
552    /// ```
553    pub async fn get_first_raw_message_by_subject<T: AsRef<str>>(
554        &self,
555        subject: T,
556        sequence: u64,
557    ) -> Result<StreamMessage, RawMessageError> {
558        self.raw_message_builder()
559            .sequence(sequence)
560            .next_by_subject(subject.as_ref().to_string())
561            .send()
562            .await
563    }
564
565    /// Get a next message from the stream for a given subject.
566    /// This low-level API always reaches stream leader.
567    /// This should be discouraged in favor of using [Stream::direct_get_next_for_subject].
568    ///
569    /// # Examples
570    ///
571    /// ```no_run
572    /// #[tokio::main]
573    /// # async fn main() -> Result<(), async_nats::Error> {
574    /// use futures_util::StreamExt;
575    /// use futures_util::TryStreamExt;
576    ///
577    /// let client = async_nats::connect("localhost:4222").await?;
578    /// let context = async_nats::jetstream::new(client);
579    /// let stream = context.get_stream_no_info("events").await?;
580    ///
581    /// let raw_message = stream
582    ///     .get_next_raw_message_by_subject("events.created")
583    ///     .await?;
584    /// println!("Retrieved raw message {:?}", raw_message);
585    /// # Ok(())
586    /// # }
587    /// ```
588    pub async fn get_next_raw_message_by_subject<T: AsRef<str>>(
589        &self,
590        subject: T,
591    ) -> Result<StreamMessage, RawMessageError> {
592        self.raw_message_builder()
593            .next_by_subject(subject.as_ref().to_string())
594            .send()
595            .await
596    }
597
598    /// Get a last message from the stream for a given subject.
599    /// This low-level API always reaches stream leader.
600    /// This should be discouraged in favor of using [Stream::direct_get_last_for_subject].
601    ///
602    /// # Examples
603    ///
604    /// ```no_run
605    /// #[tokio::main]
606    /// # async fn main() -> Result<(), async_nats::Error> {
607    /// use futures_util::StreamExt;
608    /// use futures_util::TryStreamExt;
609    ///
610    /// let client = async_nats::connect("localhost:4222").await?;
611    /// let context = async_nats::jetstream::new(client);
612    /// let stream = context.get_stream_no_info("events").await?;
613    ///
614    /// let raw_message = stream
615    ///     .get_last_raw_message_by_subject("events.created")
616    ///     .await?;
617    /// println!("Retrieved raw message {:?}", raw_message);
618    /// # Ok(())
619    /// # }
620    /// ```
621    pub async fn get_last_raw_message_by_subject(
622        &self,
623        stream_subject: &str,
624    ) -> Result<StreamMessage, LastRawMessageError> {
625        self.raw_message_builder()
626            .last_by_subject(stream_subject.to_string())
627            .send()
628            .await
629    }
630
631    /// Delete a message from the stream.
632    ///
633    /// # Examples
634    ///
635    /// ```no_run
636    /// # #[tokio::main]
637    /// # async fn main() -> Result<(), async_nats::Error> {
638    /// let client = async_nats::connect("localhost:4222").await?;
639    /// let context = async_nats::jetstream::new(client);
640    ///
641    /// let stream = context
642    ///     .get_or_create_stream(async_nats::jetstream::stream::Config {
643    ///         name: "events".to_string(),
644    ///         max_messages: 10_000,
645    ///         ..Default::default()
646    ///     })
647    ///     .await?;
648    ///
649    /// let publish_ack = context.publish("events", "data".into()).await?;
650    /// stream.delete_message(publish_ack.await?.sequence).await?;
651    /// # Ok(())
652    /// # }
653    /// ```
654    pub async fn delete_message(&self, sequence: u64) -> Result<bool, DeleteMessageError> {
655        let subject = format!("STREAM.MSG.DELETE.{}", self.name);
656        let payload = json!({
657            "seq": sequence,
658        });
659
660        let response: Response<DeleteStatus> = self
661            .context
662            .request(subject, &payload)
663            .map_err(|err| match err.kind() {
664                RequestErrorKind::TimedOut => {
665                    DeleteMessageError::new(DeleteMessageErrorKind::TimedOut)
666                }
667                _ => DeleteMessageError::with_source(DeleteMessageErrorKind::Request, err),
668            })
669            .await?;
670
671        match response {
672            Response::Err { error } => Err(DeleteMessageError::new(
673                DeleteMessageErrorKind::JetStream(error),
674            )),
675            Response::Ok(value) => Ok(value.success),
676        }
677    }
678
679    /// Purge `Stream` messages.
680    ///
681    /// # Examples
682    ///
683    /// ```no_run
684    /// # #[tokio::main]
685    /// # async fn main() -> Result<(), async_nats::Error> {
686    /// let client = async_nats::connect("demo.nats.io").await?;
687    /// let jetstream = async_nats::jetstream::new(client);
688    ///
689    /// let stream = jetstream.get_stream("events").await?;
690    /// stream.purge().await?;
691    /// # Ok(())
692    /// # }
693    /// ```
694    pub fn purge(&self) -> Purge<No, No> {
695        Purge::build(self)
696    }
697
698    /// Purge `Stream` messages for a matching subject.
699    ///
700    /// # Examples
701    ///
702    /// ```no_run
703    /// # #[tokio::main]
704    /// # #[allow(deprecated)]
705    /// # async fn main() -> Result<(), async_nats::Error> {
706    /// let client = async_nats::connect("demo.nats.io").await?;
707    /// let jetstream = async_nats::jetstream::new(client);
708    ///
709    /// let stream = jetstream.get_stream("events").await?;
710    /// stream.purge_subject("data").await?;
711    /// # Ok(())
712    /// # }
713    /// ```
714    #[deprecated(
715        since = "0.25.0",
716        note = "Overloads have been replaced with an into_future based builder. Use Stream::purge().filter(subject) instead."
717    )]
718    pub async fn purge_subject<T>(&self, subject: T) -> Result<PurgeResponse, PurgeError>
719    where
720        T: Into<String>,
721    {
722        self.purge().filter(subject).await
723    }
724
725    /// Create or update `Durable` or `Ephemeral` Consumer (if `durable_name` was not provided) and
726    /// returns the info from the server about created [Consumer]
727    /// If you want a strict update or create, use [Stream::create_consumer_strict] or [Stream::update_consumer].
728    ///
729    /// # Examples
730    ///
731    /// ```no_run
732    /// # #[tokio::main]
733    /// # async fn main() -> Result<(), async_nats::Error> {
734    /// use async_nats::jetstream::consumer;
735    /// let client = async_nats::connect("localhost:4222").await?;
736    /// let jetstream = async_nats::jetstream::new(client);
737    ///
738    /// let stream = jetstream.get_stream("events").await?;
739    /// let info = stream
740    ///     .create_consumer(consumer::pull::Config {
741    ///         durable_name: Some("pull".to_string()),
742    ///         ..Default::default()
743    ///     })
744    ///     .await?;
745    /// # Ok(())
746    /// # }
747    /// ```
748    pub async fn create_consumer<C: IntoConsumerConfig + FromConsumer>(
749        &self,
750        config: C,
751    ) -> Result<Consumer<C>, ConsumerError> {
752        self.context
753            .create_consumer_on_stream(config, self.name.clone())
754            .await
755    }
756
757    /// Update an existing consumer.
758    /// This call will fail if the consumer does not exist.
759    /// returns the info from the server about updated [Consumer].
760    ///
761    /// # Examples
762    ///
763    /// ```no_run
764    /// # #[tokio::main]
765    /// # async fn main() -> Result<(), async_nats::Error> {
766    /// use async_nats::jetstream::consumer;
767    /// let client = async_nats::connect("localhost:4222").await?;
768    /// let jetstream = async_nats::jetstream::new(client);
769    ///
770    /// let stream = jetstream.get_stream("events").await?;
771    /// let info = stream
772    ///     .update_consumer(consumer::pull::Config {
773    ///         durable_name: Some("pull".to_string()),
774    ///         ..Default::default()
775    ///     })
776    ///     .await?;
777    /// # Ok(())
778    /// # }
779    /// ```
780    #[cfg(feature = "server_2_10")]
781    pub async fn update_consumer<C: IntoConsumerConfig + FromConsumer>(
782        &self,
783        config: C,
784    ) -> Result<Consumer<C>, ConsumerUpdateError> {
785        self.context
786            .update_consumer_on_stream(config, self.name.clone())
787            .await
788    }
789
790    /// Create consumer, but only if it does not exist or the existing config is exactly
791    /// the same.
792    /// This method will fail if consumer is already present with different config.
793    /// returns the info from the server about created [Consumer].
794    ///
795    /// # Examples
796    ///
797    /// ```no_run
798    /// # #[tokio::main]
799    /// # async fn main() -> Result<(), async_nats::Error> {
800    /// use async_nats::jetstream::consumer;
801    /// let client = async_nats::connect("localhost:4222").await?;
802    /// let jetstream = async_nats::jetstream::new(client);
803    ///
804    /// let stream = jetstream.get_stream("events").await?;
805    /// let info = stream
806    ///     .create_consumer_strict(consumer::pull::Config {
807    ///         durable_name: Some("pull".to_string()),
808    ///         ..Default::default()
809    ///     })
810    ///     .await?;
811    /// # Ok(())
812    /// # }
813    /// ```
814    #[cfg(feature = "server_2_10")]
815    pub async fn create_consumer_strict<C: IntoConsumerConfig + FromConsumer>(
816        &self,
817        config: C,
818    ) -> Result<Consumer<C>, ConsumerCreateStrictError> {
819        self.context
820            .create_consumer_strict_on_stream(config, self.name.clone())
821            .await
822    }
823
824    /// Retrieve [Info] about [Consumer] from the server.
825    ///
826    /// # Examples
827    ///
828    /// ```no_run
829    /// # #[tokio::main]
830    /// # async fn main() -> Result<(), async_nats::Error> {
831    /// use async_nats::jetstream::consumer;
832    /// let client = async_nats::connect("localhost:4222").await?;
833    /// let jetstream = async_nats::jetstream::new(client);
834    ///
835    /// let stream = jetstream.get_stream("events").await?;
836    /// let info = stream.consumer_info("pull").await?;
837    /// # Ok(())
838    /// # }
839    /// ```
840    pub async fn consumer_info<T: AsRef<str>>(
841        &self,
842        name: T,
843    ) -> Result<consumer::Info, ConsumerInfoError> {
844        let name = name.as_ref();
845
846        if !is_valid_name(name) {
847            return Err(ConsumerInfoError::new(ConsumerInfoErrorKind::InvalidName));
848        }
849
850        let subject = format!("CONSUMER.INFO.{}.{}", self.name, name);
851
852        match self.context.request(subject, &json!({})).await? {
853            Response::Ok(info) => Ok(info),
854            Response::Err { error } => Err(error.into()),
855        }
856    }
857
858    /// Get [Consumer] from the the server. [Consumer] iterators can be used to retrieve
859    /// [Messages][crate::jetstream::Message] for a given [Consumer].
860    ///
861    /// # Examples
862    ///
863    /// ```no_run
864    /// # #[tokio::main]
865    /// # async fn main() -> Result<(), async_nats::Error> {
866    /// use async_nats::jetstream::consumer;
867    /// use futures_util::StreamExt;
868    /// let client = async_nats::connect("localhost:4222").await?;
869    /// let jetstream = async_nats::jetstream::new(client);
870    ///
871    /// let stream = jetstream.get_stream("events").await?;
872    /// let consumer: consumer::PullConsumer = stream.get_consumer("pull").await?;
873    /// # Ok(())
874    /// # }
875    /// ```
876    pub async fn get_consumer<T: FromConsumer + IntoConsumerConfig>(
877        &self,
878        name: &str,
879    ) -> Result<Consumer<T>, crate::Error> {
880        let info = self.consumer_info(name).await?;
881
882        Ok(Consumer::new(
883            T::try_from_consumer_config(info.config.clone())?,
884            info,
885            self.context.clone(),
886        ))
887    }
888
889    /// Create a [Consumer] with the given configuration if it is not present on the server. Returns a handle to the [Consumer].
890    ///
891    /// Note: This does not validate if the [Consumer] on the server is compatible with the configuration passed in except Push/Pull compatibility.
892    ///
893    /// # Examples
894    ///
895    /// ```no_run
896    /// # #[tokio::main]
897    /// # async fn main() -> Result<(), async_nats::Error> {
898    /// use async_nats::jetstream::consumer;
899    /// use futures_util::StreamExt;
900    /// let client = async_nats::connect("localhost:4222").await?;
901    /// let jetstream = async_nats::jetstream::new(client);
902    ///
903    /// let stream = jetstream.get_stream("events").await?;
904    /// let consumer = stream
905    ///     .get_or_create_consumer(
906    ///         "pull",
907    ///         consumer::pull::Config {
908    ///             durable_name: Some("pull".to_string()),
909    ///             ..Default::default()
910    ///         },
911    ///     )
912    ///     .await?;
913    /// # Ok(())
914    /// # }
915    /// ```
916    pub async fn get_or_create_consumer<T: FromConsumer + IntoConsumerConfig>(
917        &self,
918        name: &str,
919        config: T,
920    ) -> Result<Consumer<T>, ConsumerError> {
921        let subject = format!("CONSUMER.INFO.{}.{}", self.name, name);
922
923        match self.context.request(subject, &json!({})).await? {
924            Response::Err { error } if error.code() == 404 => self.create_consumer(config).await,
925            Response::Err { error } => Err(error.into()),
926            Response::Ok::<consumer::Info>(info) => Ok(Consumer::new(
927                T::try_from_consumer_config(info.config.clone()).map_err(|err| {
928                    ConsumerError::with_source(ConsumerErrorKind::InvalidConsumerType, err)
929                })?,
930                info,
931                self.context.clone(),
932            )),
933        }
934    }
935
936    /// Delete a [Consumer] from the server.
937    ///
938    /// # Examples
939    ///
940    /// ```no_run
941    /// # #[tokio::main]
942    /// # async fn main() -> Result<(), async_nats::Error> {
943    /// use async_nats::jetstream::consumer;
944    /// use futures_util::StreamExt;
945    /// let client = async_nats::connect("localhost:4222").await?;
946    /// let jetstream = async_nats::jetstream::new(client);
947    ///
948    /// jetstream
949    ///     .get_stream("events")
950    ///     .await?
951    ///     .delete_consumer("pull")
952    ///     .await?;
953    /// # Ok(())
954    /// # }
955    /// ```
956    pub async fn delete_consumer(&self, name: &str) -> Result<DeleteStatus, ConsumerError> {
957        let subject = format!("CONSUMER.DELETE.{}.{}", self.name, name);
958
959        match self.context.request(subject, &json!({})).await? {
960            Response::Ok(delete_status) => Ok(delete_status),
961            Response::Err { error } => Err(error.into()),
962        }
963    }
964
965    /// Pause a [Consumer] until the given time.
966    /// It will not deliver any messages to clients during that time.
967    ///
968    /// # Examples
969    ///
970    /// ```no_run
971    /// # #[tokio::main]
972    /// # async fn main() -> Result<(), async_nats::Error> {
973    /// use async_nats::jetstream::consumer;
974    /// use futures_util::StreamExt;
975    /// let client = async_nats::connect("localhost:4222").await?;
976    /// let jetstream = async_nats::jetstream::new(client);
977    /// use async_nats::datetime;
978    /// let pause_until =
979    ///     datetime::add_std_duration(datetime::now(), std::time::Duration::from_secs(10))?;
980    ///
981    /// jetstream
982    ///     .get_stream("events")
983    ///     .await?
984    ///     .pause_consumer("my_consumer", pause_until)
985    ///     .await?;
986    /// # Ok(())
987    /// # }
988    /// ```
989    #[cfg(feature = "server_2_11")]
990    pub async fn pause_consumer(
991        &self,
992        name: &str,
993        pause_until: DateTime,
994    ) -> Result<PauseResponse, ConsumerError> {
995        self.request_pause_consumer(name, Some(pause_until)).await
996    }
997
998    /// Resume a paused [Consumer].
999    ///
1000    /// # Examples
1001    ///
1002    /// ```no_run
1003    /// # #[tokio::main]
1004    /// # async fn main() -> Result<(), async_nats::Error> {
1005    /// use async_nats::jetstream::consumer;
1006    /// use futures_util::StreamExt;
1007    /// let client = async_nats::connect("localhost:4222").await?;
1008    /// let jetstream = async_nats::jetstream::new(client);
1009    ///
1010    /// jetstream
1011    ///     .get_stream("events")
1012    ///     .await?
1013    ///     .resume_consumer("my_consumer")
1014    ///     .await?;
1015    /// # Ok(())
1016    /// # }
1017    /// ```
1018    #[cfg(feature = "server_2_11")]
1019    pub async fn resume_consumer(&self, name: &str) -> Result<PauseResponse, ConsumerError> {
1020        self.request_pause_consumer(name, None).await
1021    }
1022
1023    #[cfg(feature = "server_2_11")]
1024    async fn request_pause_consumer(
1025        &self,
1026        name: &str,
1027        pause_until: Option<DateTime>,
1028    ) -> Result<PauseResponse, ConsumerError> {
1029        let subject = format!("CONSUMER.PAUSE.{}.{}", self.name, name);
1030        let payload = &PauseResumeConsumerRequest { pause_until };
1031
1032        match self.context.request(subject, payload).await? {
1033            Response::Ok::<PauseResponse>(resp) => Ok(resp),
1034            Response::Err { error } => Err(error.into()),
1035        }
1036    }
1037
1038    /// Reset a [Consumer]'s delivery state (ADR-60).
1039    ///
1040    /// `seq` semantics:
1041    /// - `None` (or `Some(0)`): reset back to the consumer's ack floor.
1042    ///   Pending and redelivered messages are cleared; the ack-floor stream
1043    ///   sequence is left where it was.
1044    /// - `Some(n)` with `n > 0`: ack-floor stream sequence is set to one
1045    ///   below `n`; the next delivered message will have a stream sequence
1046    ///   of at least `n`.
1047    ///
1048    /// Only valid on consumers with
1049    /// [`DeliverPolicy::All`][crate::jetstream::consumer::DeliverPolicy::All],
1050    /// [`DeliverPolicy::ByStartSequence`][crate::jetstream::consumer::DeliverPolicy::ByStartSequence],
1051    /// or
1052    /// [`DeliverPolicy::ByStartTime`][crate::jetstream::consumer::DeliverPolicy::ByStartTime].
1053    /// For policies with a configured starting sequence/time, resets below
1054    /// the configured start are rejected by the server.
1055    ///
1056    /// # Examples
1057    ///
1058    /// ```no_run
1059    /// # #[tokio::main]
1060    /// # async fn main() -> Result<(), async_nats::Error> {
1061    /// let client = async_nats::connect("localhost:4222").await?;
1062    /// let jetstream = async_nats::jetstream::new(client);
1063    ///
1064    /// let stream = jetstream.get_stream("events").await?;
1065    /// stream.reset_consumer("processor", Some(42)).await?;
1066    /// # Ok(())
1067    /// # }
1068    /// ```
1069    #[cfg(feature = "server_2_14")]
1070    #[cfg_attr(docsrs, doc(cfg(feature = "server_2_14")))]
1071    pub async fn reset_consumer(
1072        &self,
1073        name: &str,
1074        seq: Option<u64>,
1075    ) -> Result<ConsumerResetResponse, ConsumerResetError> {
1076        let subject = format!("CONSUMER.RESET.{}.{}", self.name, name);
1077        let payload = ConsumerResetRequest {
1078            seq: seq.unwrap_or(0),
1079        };
1080
1081        match self.context.request(subject, &payload).await? {
1082            Response::Ok::<ConsumerResetResponse>(resp) => Ok(resp),
1083            Response::Err { error } => Err(error.into()),
1084        }
1085    }
1086
1087    /// Lists names of all consumers for current stream.
1088    ///
1089    /// # Examples
1090    ///
1091    /// ```no_run
1092    /// # #[tokio::main]
1093    /// # async fn main() -> Result<(), async_nats::Error> {
1094    /// use futures_util::TryStreamExt;
1095    /// let client = async_nats::connect("demo.nats.io:4222").await?;
1096    /// let jetstream = async_nats::jetstream::new(client);
1097    /// let stream = jetstream.get_stream("stream").await?;
1098    /// let mut names = stream.consumer_names();
1099    /// while let Some(consumer) = names.try_next().await? {
1100    ///     println!("consumer: {stream:?}");
1101    /// }
1102    /// # Ok(())
1103    /// # }
1104    /// ```
1105    pub fn consumer_names(&self) -> ConsumerNames {
1106        ConsumerNames {
1107            context: self.context.clone(),
1108            stream: self.name.clone(),
1109            offset: 0,
1110            page_request: None,
1111            consumers: Vec::new(),
1112            done: false,
1113        }
1114    }
1115
1116    /// Lists all consumers info for current stream.
1117    ///
1118    /// # Examples
1119    ///
1120    /// ```no_run
1121    /// # #[tokio::main]
1122    /// # async fn main() -> Result<(), async_nats::Error> {
1123    /// use futures_util::TryStreamExt;
1124    /// let client = async_nats::connect("demo.nats.io:4222").await?;
1125    /// let jetstream = async_nats::jetstream::new(client);
1126    /// let stream = jetstream.get_stream("stream").await?;
1127    /// let mut consumers = stream.consumers();
1128    /// while let Some(consumer) = consumers.try_next().await? {
1129    ///     println!("consumer: {consumer:?}");
1130    /// }
1131    /// # Ok(())
1132    /// # }
1133    /// ```
1134    pub fn consumers(&self) -> Consumers {
1135        Consumers {
1136            context: self.context.clone(),
1137            stream: self.name.clone(),
1138            offset: 0,
1139            page_request: None,
1140            consumers: Vec::new(),
1141            done: false,
1142        }
1143    }
1144}
1145
1146pub struct StreamInfoBuilder {
1147    pub(crate) context: Context,
1148    pub(crate) name: String,
1149    pub(crate) deleted: bool,
1150    pub(crate) subject: String,
1151}
1152
1153impl StreamInfoBuilder {
1154    fn new(context: Context, name: String) -> Self {
1155        Self {
1156            context,
1157            name,
1158            deleted: false,
1159            subject: "".to_string(),
1160        }
1161    }
1162
1163    pub fn with_deleted(mut self, deleted: bool) -> Self {
1164        self.deleted = deleted;
1165        self
1166    }
1167
1168    pub fn subjects<S: Into<String>>(mut self, subject: S) -> Self {
1169        self.subject = subject.into();
1170        self
1171    }
1172
1173    pub async fn fetch(self) -> Result<InfoWithSubjects, InfoError> {
1174        let info = stream_info_with_details(
1175            self.context.clone(),
1176            self.name.clone(),
1177            0,
1178            self.deleted,
1179            self.subject.clone(),
1180        )
1181        .await?;
1182
1183        Ok(InfoWithSubjects::new(self.context, info, self.subject))
1184    }
1185}
1186
1187/// `StreamConfig` determines the properties for a stream.
1188/// There are sensible defaults for most. If no subjects are
1189/// given the name will be used as the only subject.
1190#[derive(Debug, Default, Serialize, Deserialize, Clone, PartialEq, Eq)]
1191pub struct Config {
1192    /// A name for the Stream. Must not have spaces, tabs or period `.` characters
1193    pub name: String,
1194    /// How large the Stream may become in total bytes before the configured discard policy kicks in
1195    #[serde(default)]
1196    pub max_bytes: i64,
1197    /// How large the Stream may become in total messages before the configured discard policy kicks in
1198    #[serde(default, rename = "max_msgs")]
1199    pub max_messages: i64,
1200    /// Maximum amount of messages to keep per subject
1201    #[serde(default, rename = "max_msgs_per_subject")]
1202    pub max_messages_per_subject: i64,
1203    /// When a Stream has reached its configured `max_bytes` or `max_msgs`, this policy kicks in.
1204    /// `DiscardPolicy::New` refuses new messages or `DiscardPolicy::Old` (default) deletes old messages to make space
1205    pub discard: DiscardPolicy,
1206    /// Prevents a message from being added to a stream if the max_msgs_per_subject limit for the subject has been reached
1207    #[serde(default, skip_serializing_if = "is_default")]
1208    pub discard_new_per_subject: bool,
1209    /// Which NATS subjects to populate this stream with. Supports wildcards. Defaults to just the
1210    /// configured stream `name`.
1211    #[serde(default, skip_serializing_if = "Vec::is_empty")]
1212    pub subjects: Vec<String>,
1213    /// How message retention is considered, `Limits` (default), `Interest` or `WorkQueue`
1214    pub retention: RetentionPolicy,
1215    /// How many Consumers can be defined for a given Stream, -1 for unlimited
1216    #[serde(default)]
1217    pub max_consumers: i32,
1218    /// Maximum age of any message in the stream, expressed in nanoseconds
1219    #[serde(default, with = "serde_nanos")]
1220    pub max_age: Duration,
1221    /// The largest message that will be accepted by the Stream
1222    #[serde(default, skip_serializing_if = "is_default", rename = "max_msg_size")]
1223    pub max_message_size: i32,
1224    /// The type of storage backend, `File` (default) and `Memory`
1225    pub storage: StorageType,
1226    /// How many replicas to keep for each message in a clustered JetStream, maximum 5
1227    pub num_replicas: usize,
1228    /// Disables acknowledging messages that are received by the Stream
1229    #[serde(default, skip_serializing_if = "is_default")]
1230    pub no_ack: bool,
1231    /// The window within which to track duplicate messages.
1232    #[serde(default, skip_serializing_if = "is_default", with = "serde_nanos")]
1233    pub duplicate_window: Duration,
1234    /// The owner of the template associated with this stream.
1235    #[serde(default, skip_serializing_if = "is_default")]
1236    pub template_owner: String,
1237    /// Indicates the stream is sealed and cannot be modified in any way
1238    #[serde(default, skip_serializing_if = "is_default")]
1239    pub sealed: bool,
1240    /// A short description of the purpose of this stream.
1241    #[serde(default, skip_serializing_if = "is_default")]
1242    pub description: Option<String>,
1243    #[serde(
1244        default,
1245        rename = "allow_rollup_hdrs",
1246        skip_serializing_if = "is_default"
1247    )]
1248    /// Indicates if rollups will be allowed or not.
1249    pub allow_rollup: bool,
1250    #[serde(default, skip_serializing_if = "is_default")]
1251    /// Indicates deletes will be denied or not.
1252    pub deny_delete: bool,
1253    /// Indicates if purges will be denied or not.
1254    #[serde(default, skip_serializing_if = "is_default")]
1255    pub deny_purge: bool,
1256
1257    /// Optional republish config.
1258    #[serde(default, skip_serializing_if = "is_default")]
1259    pub republish: Option<Republish>,
1260
1261    /// Enables direct get, which would get messages from
1262    /// non-leader.
1263    #[serde(default, skip_serializing_if = "is_default")]
1264    pub allow_direct: bool,
1265
1266    /// Enable direct access also for mirrors.
1267    #[serde(default, skip_serializing_if = "is_default")]
1268    pub mirror_direct: bool,
1269
1270    /// Stream mirror configuration.
1271    #[serde(default, skip_serializing_if = "Option::is_none")]
1272    pub mirror: Option<Source>,
1273
1274    /// Sources configuration.
1275    #[serde(default, skip_serializing_if = "Option::is_none")]
1276    pub sources: Option<Vec<Source>>,
1277
1278    #[cfg(feature = "server_2_10")]
1279    /// Additional stream metadata.
1280    #[serde(default, skip_serializing_if = "is_default")]
1281    pub metadata: HashMap<String, String>,
1282
1283    #[cfg(feature = "server_2_10")]
1284    /// Allow applying a subject transform to incoming messages
1285    #[serde(default, skip_serializing_if = "Option::is_none")]
1286    pub subject_transform: Option<SubjectTransform>,
1287
1288    #[cfg(feature = "server_2_10")]
1289    /// Override compression config for this stream.
1290    /// Wrapping enum that has `None` type with [Option] is there
1291    /// because [Stream] can override global compression set to [Compression::S2]
1292    /// to [Compression::None], which is different from not overriding global config with anything.
1293    #[serde(default, skip_serializing_if = "Option::is_none")]
1294    pub compression: Option<Compression>,
1295    #[cfg(feature = "server_2_10")]
1296    /// Set limits on consumers that are created on this stream.
1297    #[serde(default, deserialize_with = "default_consumer_limits_as_none")]
1298    pub consumer_limits: Option<ConsumerLimits>,
1299
1300    #[cfg(feature = "server_2_10")]
1301    /// Sets the first sequence for the stream.
1302    #[serde(default, skip_serializing_if = "Option::is_none", rename = "first_seq")]
1303    pub first_sequence: Option<u64>,
1304
1305    /// Placement configuration for clusters and tags.
1306    #[serde(default, skip_serializing_if = "Option::is_none")]
1307    pub placement: Option<Placement>,
1308
1309    /// Persistence mode for the stream.
1310    #[serde(default, skip_serializing_if = "Option::is_none")]
1311    pub persist_mode: Option<PersistenceMode>,
1312
1313    /// For suspending the consumer until the deadline.
1314    #[cfg(feature = "server_2_11")]
1315    #[serde(
1316        default,
1317        with = "rfc3339::option",
1318        skip_serializing_if = "Option::is_none"
1319    )]
1320    pub pause_until: Option<DateTime>,
1321
1322    /// Allows setting a TTL for a message in the stream.
1323    #[cfg(feature = "server_2_11")]
1324    #[serde(default, skip_serializing_if = "is_default", rename = "allow_msg_ttl")]
1325    pub allow_message_ttl: bool,
1326
1327    /// Enables delete markers for messages deleted from the stream and sets the TTL
1328    /// for how long the marker should be kept.
1329    #[cfg(feature = "server_2_11")]
1330    #[serde(default, skip_serializing_if = "Option::is_none", with = "serde_nanos")]
1331    pub subject_delete_marker_ttl: Option<Duration>,
1332
1333    /// Allows atomic publish operations.
1334    #[cfg(feature = "server_2_12")]
1335    #[serde(default, skip_serializing_if = "is_default", rename = "allow_atomic")]
1336    pub allow_atomic_publish: bool,
1337
1338    /// Enables the scheduling of messages
1339    #[cfg(feature = "server_2_12")]
1340    #[serde(
1341        default,
1342        skip_serializing_if = "is_default",
1343        rename = "allow_msg_schedules"
1344    )]
1345    pub allow_message_schedules: bool,
1346
1347    /// Enables counters for the stream
1348    #[cfg(feature = "server_2_12")]
1349    #[serde(
1350        default,
1351        skip_serializing_if = "is_default",
1352        rename = "allow_msg_counter"
1353    )]
1354    pub allow_message_counter: bool,
1355
1356    /// Allows fast-ingest batch publishing on the stream (ADR-50).
1357    #[cfg(feature = "server_2_14")]
1358    #[cfg_attr(docsrs, doc(cfg(feature = "server_2_14")))]
1359    #[serde(default, skip_serializing_if = "is_default", rename = "allow_batched")]
1360    pub allow_batch_publish: bool,
1361}
1362
1363impl From<&Config> for Config {
1364    fn from(sc: &Config) -> Config {
1365        sc.clone()
1366    }
1367}
1368
1369impl From<&str> for Config {
1370    fn from(s: &str) -> Config {
1371        Config {
1372            name: s.to_string(),
1373            ..Default::default()
1374        }
1375    }
1376}
1377
1378#[cfg(feature = "server_2_10")]
1379fn default_consumer_limits_as_none<'de, D>(
1380    deserializer: D,
1381) -> Result<Option<ConsumerLimits>, D::Error>
1382where
1383    D: Deserializer<'de>,
1384{
1385    let consumer_limits = Option::<ConsumerLimits>::deserialize(deserializer)?;
1386    if let Some(cl) = consumer_limits {
1387        if cl == ConsumerLimits::default() {
1388            Ok(None)
1389        } else {
1390            Ok(Some(cl))
1391        }
1392    } else {
1393        Ok(None)
1394    }
1395}
1396#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, Default)]
1397pub struct ConsumerLimits {
1398    /// Sets the maximum [crate::jetstream::consumer::Config::inactive_threshold] that can be set on the consumer.
1399    #[serde(default, with = "serde_nanos")]
1400    pub inactive_threshold: std::time::Duration,
1401    /// Sets the maximum [crate::jetstream::consumer::Config::max_ack_pending] that can be set on the consumer.
1402    #[serde(default)]
1403    pub max_ack_pending: i64,
1404}
1405
1406#[derive(Serialize, Deserialize, Debug, Clone, Eq, PartialEq)]
1407pub enum Compression {
1408    #[serde(rename = "s2")]
1409    S2,
1410    #[serde(rename = "none")]
1411    None,
1412}
1413
1414// SubjectTransform is for applying a subject transform (to matching messages) when a new message is received
1415#[derive(Serialize, Deserialize, Debug, Clone, Eq, PartialEq)]
1416pub struct SubjectTransform {
1417    #[serde(rename = "src")]
1418    pub source: String,
1419
1420    #[serde(rename = "dest")]
1421    pub destination: String,
1422}
1423
1424// Republish is for republishing messages once committed to a stream.
1425#[derive(Serialize, Deserialize, Debug, Clone, Eq, PartialEq)]
1426pub struct Republish {
1427    /// Subject that should be republished.
1428    #[serde(rename = "src")]
1429    pub source: String,
1430    /// Subject where messages will be republished.
1431    #[serde(rename = "dest")]
1432    pub destination: String,
1433    /// If true, only headers should be republished.
1434    #[serde(default)]
1435    pub headers_only: bool,
1436}
1437
1438/// Placement describes on which cluster or tags the stream should be placed.
1439#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq, Eq)]
1440pub struct Placement {
1441    // Cluster where the stream should be placed.
1442    #[serde(default, skip_serializing_if = "is_default")]
1443    pub cluster: Option<String>,
1444    // Matching tags for stream placement.
1445    #[serde(default, skip_serializing_if = "is_default")]
1446    pub tags: Vec<String>,
1447}
1448
1449/// `DiscardPolicy` determines how we proceed when limits of messages or bytes are hit. The default, `Old` will
1450/// remove older messages. `New` will fail to store the new message.
1451#[derive(Default, Debug, Serialize, Deserialize, Clone, Copy, PartialEq, Eq)]
1452#[repr(u8)]
1453pub enum DiscardPolicy {
1454    /// will remove older messages when limits are hit.
1455    #[default]
1456    #[serde(rename = "old")]
1457    Old = 0,
1458    /// will error on a StoreMsg call when limits are hit
1459    #[serde(rename = "new")]
1460    New = 1,
1461}
1462
1463/// `RetentionPolicy` determines how messages in a set are retained.
1464#[derive(Default, Debug, Serialize, Deserialize, Clone, Copy, PartialEq, Eq)]
1465#[repr(u8)]
1466pub enum RetentionPolicy {
1467    /// `Limits` (default) means that messages are retained until any given limit is reached.
1468    /// This could be one of messages, bytes, or age.
1469    #[default]
1470    #[serde(rename = "limits")]
1471    Limits = 0,
1472    /// `Interest` specifies that when all known observables have acknowledged a message it can be removed.
1473    #[serde(rename = "interest")]
1474    Interest = 1,
1475    /// `WorkQueue` specifies that when the first worker or subscriber acknowledges the message it can be removed.
1476    #[serde(rename = "workqueue")]
1477    WorkQueue = 2,
1478}
1479
1480/// determines how messages are stored for retention.
1481#[derive(Default, Debug, Serialize, Deserialize, Clone, Copy, PartialEq, Eq)]
1482#[repr(u8)]
1483pub enum StorageType {
1484    /// Stream data is kept in files. This is the default.
1485    #[default]
1486    #[serde(rename = "file")]
1487    File = 0,
1488    /// Stream data is kept only in memory.
1489    #[serde(rename = "memory")]
1490    Memory = 1,
1491}
1492
1493/// Determines the persistence mode for stream data.
1494#[derive(Default, Debug, Serialize, Deserialize, Clone, Copy, PartialEq, Eq)]
1495#[repr(u8)]
1496pub enum PersistenceMode {
1497    /// Writes are immediately flushed, acknowledgement sent after message is stored.
1498    #[default]
1499    #[serde(rename = "default")]
1500    Default = 0,
1501    /// Writes are flushed asynchronously, acknowledgement may be sent before message is stored.
1502    #[serde(rename = "async")]
1503    Async = 1,
1504}
1505
1506async fn stream_info_with_details(
1507    context: Context,
1508    stream: String,
1509    offset: usize,
1510    deleted_details: bool,
1511    subjects_filter: String,
1512) -> Result<Info, InfoError> {
1513    let subject = format!("STREAM.INFO.{stream}");
1514
1515    let payload = StreamInfoRequest {
1516        offset,
1517        deleted_details,
1518        subjects_filter,
1519    };
1520
1521    let response: Response<Info> = context.request(subject, &payload).await?;
1522
1523    match response {
1524        Response::Ok(info) => Ok(info),
1525        Response::Err { error } => Err(error.into()),
1526    }
1527}
1528
1529type InfoRequest = BoxFuture<'static, Result<Info, InfoError>>;
1530
1531#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
1532pub struct StreamInfoRequest {
1533    offset: usize,
1534    deleted_details: bool,
1535    subjects_filter: String,
1536}
1537
1538pub struct InfoWithSubjects {
1539    stream: String,
1540    context: Context,
1541    pub info: Info,
1542    offset: usize,
1543    subjects: collections::hash_map::IntoIter<String, usize>,
1544    info_request: Option<InfoRequest>,
1545    subjects_filter: String,
1546    pages_done: bool,
1547}
1548
1549impl InfoWithSubjects {
1550    pub fn new(context: Context, mut info: Info, subject: String) -> Self {
1551        let subjects = info.state.subjects.take().unwrap_or_default();
1552        let name = info.config.name.clone();
1553        InfoWithSubjects {
1554            context,
1555            info,
1556            pages_done: subjects.is_empty(),
1557            offset: subjects.len(),
1558            subjects: subjects.into_iter(),
1559            subjects_filter: subject,
1560            stream: name,
1561            info_request: None,
1562        }
1563    }
1564}
1565
1566impl futures_util::Stream for InfoWithSubjects {
1567    type Item = Result<(String, usize), InfoError>;
1568
1569    fn poll_next(
1570        mut self: Pin<&mut Self>,
1571        cx: &mut std::task::Context<'_>,
1572    ) -> Poll<Option<Self::Item>> {
1573        match self.subjects.next() {
1574            Some((subject, count)) => Poll::Ready(Some(Ok((subject, count)))),
1575            None => {
1576                // If we have already requested all pages, stop the iterator.
1577                if self.pages_done {
1578                    return Poll::Ready(None);
1579                }
1580                let stream = self.stream.clone();
1581                let context = self.context.clone();
1582                let subjects_filter = self.subjects_filter.clone();
1583                let offset = self.offset;
1584                match self
1585                    .info_request
1586                    .get_or_insert_with(|| {
1587                        Box::pin(stream_info_with_details(
1588                            context,
1589                            stream,
1590                            offset,
1591                            false,
1592                            subjects_filter,
1593                        ))
1594                    })
1595                    .poll_unpin(cx)
1596                {
1597                    Poll::Ready(resp) => match resp {
1598                        Ok(info) => {
1599                            let subjects = info.state.subjects.clone();
1600                            self.offset += subjects.as_ref().map_or_else(|| 0, |s| s.len());
1601                            self.info_request = None;
1602                            let subjects = subjects.unwrap_or_default();
1603                            self.subjects = info.state.subjects.unwrap_or_default().into_iter();
1604                            let total = info.paged_info.map(|info| info.total).unwrap_or(0);
1605                            if total <= self.offset || subjects.is_empty() {
1606                                self.pages_done = true;
1607                            }
1608                            match self.subjects.next() {
1609                                Some((subject, count)) => Poll::Ready(Some(Ok((subject, count)))),
1610                                None => Poll::Ready(None),
1611                            }
1612                        }
1613                        Err(err) => Poll::Ready(Some(Err(err))),
1614                    },
1615                    Poll::Pending => Poll::Pending,
1616                }
1617            }
1618        }
1619    }
1620}
1621
1622/// Shows config and current state for this stream.
1623#[derive(Debug, Deserialize, Clone, PartialEq, Eq)]
1624pub struct Info {
1625    /// The configuration associated with this stream.
1626    pub config: Config,
1627    /// The time that this stream was created.
1628    #[serde(with = "rfc3339")]
1629    pub created: DateTime,
1630    /// Various metrics associated with this stream.
1631    pub state: State,
1632    /// Information about leader and replicas.
1633    pub cluster: Option<ClusterInfo>,
1634    /// Information about mirror config if present.
1635    #[serde(default)]
1636    pub mirror: Option<SourceInfo>,
1637    /// Information about sources configs if present.
1638    #[serde(default)]
1639    pub sources: Vec<SourceInfo>,
1640    #[serde(flatten)]
1641    paged_info: Option<PagedInfo>,
1642}
1643
1644#[derive(Debug, Deserialize, Clone, PartialEq, Eq)]
1645pub struct PagedInfo {
1646    offset: usize,
1647    total: usize,
1648    limit: usize,
1649}
1650
1651#[derive(Deserialize)]
1652pub struct DeleteStatus {
1653    pub success: bool,
1654}
1655
1656#[cfg(feature = "server_2_11")]
1657#[derive(Deserialize)]
1658pub struct PauseResponse {
1659    pub paused: bool,
1660    #[serde(with = "rfc3339")]
1661    pub pause_until: DateTime,
1662    #[serde(default, with = "serde_nanos")]
1663    pub pause_remaining: Option<Duration>,
1664}
1665
1666#[cfg(feature = "server_2_11")]
1667#[derive(Serialize, Debug)]
1668struct PauseResumeConsumerRequest {
1669    #[serde(with = "rfc3339::option", skip_serializing_if = "Option::is_none")]
1670    pause_until: Option<DateTime>,
1671}
1672
1673#[cfg(feature = "server_2_14")]
1674#[derive(Serialize, Debug)]
1675pub(crate) struct ConsumerResetRequest {
1676    #[serde(default, skip_serializing_if = "is_default")]
1677    pub(crate) seq: u64,
1678}
1679
1680/// Response from a [`Stream::reset_consumer`] / [`crate::jetstream::consumer::Consumer::reset`] call.
1681#[cfg(feature = "server_2_14")]
1682#[cfg_attr(docsrs, doc(cfg(feature = "server_2_14")))]
1683#[derive(Debug, Deserialize, Clone)]
1684pub struct ConsumerResetResponse {
1685    /// Refreshed [Info][crate::jetstream::consumer::Info] for the consumer
1686    /// after the reset has been applied.
1687    #[serde(flatten)]
1688    pub info: super::consumer::Info,
1689    /// Stream sequence the consumer's ack floor is now sitting at after the
1690    /// reset. For an empty / `None` request this echoes the previously held
1691    /// ack-floor seq.
1692    pub reset_seq: u64,
1693}
1694
1695/// information about the given stream.
1696#[derive(Debug, Deserialize, Clone, PartialEq, Eq)]
1697pub struct State {
1698    /// The number of messages contained in this stream
1699    pub messages: u64,
1700    /// The number of bytes of all messages contained in this stream
1701    pub bytes: u64,
1702    /// The lowest sequence number still present in this stream
1703    #[serde(rename = "first_seq")]
1704    pub first_sequence: u64,
1705    /// The time associated with the oldest message still present in this stream
1706    #[serde(with = "rfc3339", rename = "first_ts")]
1707    pub first_timestamp: DateTime,
1708    /// The last sequence number assigned to a message in this stream
1709    #[serde(rename = "last_seq")]
1710    pub last_sequence: u64,
1711    /// The time that the last message was received by this stream
1712    #[serde(with = "rfc3339", rename = "last_ts")]
1713    pub last_timestamp: DateTime,
1714    /// The number of consumers configured to consume this stream
1715    pub consumer_count: usize,
1716    /// The number of subjects in the stream
1717    #[serde(default, rename = "num_subjects")]
1718    pub subjects_count: u64,
1719    /// The number of deleted messages in the stream
1720    #[serde(default, rename = "num_deleted")]
1721    pub deleted_count: Option<u64>,
1722    /// The list of deleted subjects from the Stream.
1723    /// This field will be filled only if [[StreamInfoBuilder::with_deleted]] option is set.
1724    #[serde(default)]
1725    pub deleted: Option<Vec<u64>>,
1726
1727    pub(crate) subjects: Option<HashMap<String, usize>>,
1728}
1729
1730/// A raw stream message in the representation it is stored.
1731#[derive(Debug, Serialize, Deserialize, Clone)]
1732pub struct RawMessage {
1733    /// Subject of the message.
1734    #[serde(rename = "subject")]
1735    pub subject: String,
1736
1737    /// Sequence of the message.
1738    #[serde(rename = "seq")]
1739    pub sequence: u64,
1740
1741    /// Raw payload of the message as a base64 encoded string.
1742    #[serde(default, rename = "data")]
1743    pub payload: String,
1744
1745    /// Raw header string, if any.
1746    #[serde(default, rename = "hdrs")]
1747    pub headers: Option<String>,
1748
1749    /// The time the message was published.
1750    #[serde(rename = "time", with = "rfc3339")]
1751    pub time: DateTime,
1752}
1753
1754impl TryFrom<RawMessage> for StreamMessage {
1755    type Error = crate::Error;
1756
1757    fn try_from(value: RawMessage) -> Result<Self, Self::Error> {
1758        let decoded_payload = STANDARD
1759            .decode(value.payload)
1760            .map_err(|err| Box::new(std::io::Error::other(err)))?;
1761        let decoded_headers = value
1762            .headers
1763            .map(|header| STANDARD.decode(header))
1764            .map_or(Ok(None), |v| v.map(Some))?;
1765
1766        let (headers, _, _) = decoded_headers
1767            .map_or_else(|| Ok((HeaderMap::new(), None, None)), |h| parse_headers(&h))?;
1768
1769        Ok(StreamMessage {
1770            subject: value.subject.into(),
1771            payload: decoded_payload.into(),
1772            headers,
1773            sequence: value.sequence,
1774            time: value.time,
1775        })
1776    }
1777}
1778
1779fn is_continuation(c: char) -> bool {
1780    c == ' ' || c == '\t'
1781}
1782const HEADER_LINE: &str = "NATS/1.0";
1783
1784#[allow(clippy::type_complexity)]
1785fn parse_headers(
1786    buf: &[u8],
1787) -> Result<(HeaderMap, Option<StatusCode>, Option<String>), crate::Error> {
1788    let mut headers = HeaderMap::new();
1789    let mut maybe_status: Option<StatusCode> = None;
1790    let mut maybe_description: Option<String> = None;
1791    let mut lines = if let Ok(line) = std::str::from_utf8(buf) {
1792        line.lines().peekable()
1793    } else {
1794        return Err(Box::new(std::io::Error::other("invalid header")));
1795    };
1796
1797    if let Some(line) = lines.next() {
1798        let line = line
1799            .strip_prefix(HEADER_LINE)
1800            .ok_or_else(|| {
1801                Box::new(std::io::Error::other(
1802                    "version line does not start with NATS/1.0",
1803                ))
1804            })?
1805            .trim();
1806
1807        match line.split_once(' ') {
1808            Some((status, description)) => {
1809                if !status.is_empty() {
1810                    maybe_status = Some(status.parse()?);
1811                }
1812
1813                if !description.is_empty() {
1814                    maybe_description = Some(description.trim().to_string());
1815                }
1816            }
1817            None => {
1818                if !line.is_empty() {
1819                    maybe_status = Some(line.parse()?);
1820                }
1821            }
1822        }
1823    } else {
1824        return Err(Box::new(std::io::Error::other(
1825            "expected header information not found",
1826        )));
1827    };
1828
1829    while let Some(line) = lines.next() {
1830        if line.is_empty() {
1831            continue;
1832        }
1833
1834        if let Some((k, v)) = line.split_once(':').to_owned() {
1835            let mut s = String::from(v.trim());
1836            while let Some(v) = lines.next_if(|s| s.starts_with(is_continuation)).to_owned() {
1837                s.push(' ');
1838                s.push_str(v.trim());
1839            }
1840
1841            headers.insert(
1842                HeaderName::from_str(k)?,
1843                HeaderValue::from_str(&s).map_err(|err| Box::new(io::Error::other(err)))?,
1844            );
1845        } else {
1846            return Err(Box::new(std::io::Error::other("malformed header line")));
1847        }
1848    }
1849
1850    if headers.is_empty() {
1851        Ok((HeaderMap::new(), maybe_status, maybe_description))
1852    } else {
1853        Ok((headers, maybe_status, maybe_description))
1854    }
1855}
1856
1857#[derive(Debug, Serialize, Deserialize, Clone)]
1858struct GetRawMessage {
1859    pub(crate) message: RawMessage,
1860}
1861
1862fn is_default<T: Default + Eq>(t: &T) -> bool {
1863    t == &T::default()
1864}
1865/// Information about the stream's, consumer's associated `JetStream` cluster
1866#[derive(Debug, Default, Deserialize, Clone, PartialEq, Eq)]
1867pub struct ClusterInfo {
1868    /// The cluster name.
1869    #[serde(default)]
1870    pub name: Option<String>,
1871    /// The RAFT group name.
1872    #[serde(default)]
1873    pub raft_group: Option<String>,
1874    /// The server name of the RAFT leader.
1875    #[serde(default)]
1876    pub leader: Option<String>,
1877    /// The time since this server has been the leader.
1878    #[serde(default, with = "rfc3339::option")]
1879    pub leader_since: Option<DateTime>,
1880    /// Indicates if this account is a system account.
1881    #[cfg(feature = "server_2_12")]
1882    #[serde(default)]
1883    /// Indicates if `traffic_account` is set a system account.
1884    pub system_account: bool,
1885    #[cfg(feature = "server_2_12")]
1886    /// Name of the traffic (replication) account.
1887    #[serde(default)]
1888    pub traffic_account: Option<String>,
1889    /// The members of the RAFT cluster.
1890    #[serde(default)]
1891    pub replicas: Vec<PeerInfo>,
1892}
1893
1894/// The members of the RAFT cluster
1895#[derive(Debug, Default, Deserialize, Clone, PartialEq, Eq)]
1896pub struct PeerInfo {
1897    /// The server name of the peer.
1898    pub name: String,
1899    /// Indicates if the server is up to date and synchronized.
1900    pub current: bool,
1901    /// Nanoseconds since this peer was last seen.
1902    #[serde(with = "serde_nanos")]
1903    pub active: Duration,
1904    /// Indicates the node is considered offline by the group.
1905    #[serde(default)]
1906    pub offline: bool,
1907    /// How many uncommitted operations this peer is behind the leader.
1908    pub lag: Option<u64>,
1909}
1910
1911#[derive(Debug, Clone, Deserialize, PartialEq, Eq)]
1912pub struct SourceInfo {
1913    /// Source name.
1914    pub name: String,
1915    /// Number of messages this source is lagging behind.
1916    pub lag: u64,
1917    /// Last time the source was seen active.
1918    #[serde(deserialize_with = "negative_duration_as_none")]
1919    pub active: Option<std::time::Duration>,
1920    /// Filtering for the source.
1921    #[serde(default)]
1922    pub filter_subject: Option<String>,
1923    /// Source destination subject.
1924    #[serde(default)]
1925    pub subject_transform_dest: Option<String>,
1926    /// List of transforms.
1927    #[serde(default)]
1928    pub subject_transforms: Vec<SubjectTransform>,
1929}
1930
1931fn negative_duration_as_none<'de, D>(
1932    deserializer: D,
1933) -> Result<Option<std::time::Duration>, D::Error>
1934where
1935    D: Deserializer<'de>,
1936{
1937    let n = i64::deserialize(deserializer)?;
1938    if n.is_negative() {
1939        Ok(None)
1940    } else {
1941        Ok(Some(std::time::Duration::from_nanos(n as u64)))
1942    }
1943}
1944
1945/// The response generated by trying to purge a stream.
1946#[derive(Debug, Deserialize, Clone, Copy)]
1947pub struct PurgeResponse {
1948    /// Whether the purge request was successful.
1949    pub success: bool,
1950    /// The number of purged messages in a stream.
1951    pub purged: u64,
1952}
1953/// The payload used to generate a purge request.
1954#[derive(Default, Debug, Serialize, Clone)]
1955pub struct PurgeRequest {
1956    /// Purge up to but not including sequence.
1957    #[serde(default, rename = "seq", skip_serializing_if = "is_default")]
1958    pub sequence: Option<u64>,
1959
1960    /// Subject to match against messages for the purge command.
1961    #[serde(default, skip_serializing_if = "is_default")]
1962    pub filter: Option<String>,
1963
1964    /// Number of messages to keep.
1965    #[serde(default, skip_serializing_if = "is_default")]
1966    pub keep: Option<u64>,
1967}
1968
1969#[derive(Clone, Debug, Serialize, Deserialize, Eq, PartialEq, Default)]
1970pub struct Source {
1971    /// Name of the stream source.
1972    pub name: String,
1973    /// Optional source start sequence.
1974    #[serde(default, rename = "opt_start_seq", skip_serializing_if = "is_default")]
1975    pub start_sequence: Option<u64>,
1976    #[serde(
1977        default,
1978        rename = "opt_start_time",
1979        skip_serializing_if = "is_default",
1980        with = "rfc3339::option"
1981    )]
1982    /// Optional source start time.
1983    pub start_time: Option<DateTime>,
1984    /// Optional additional filter subject.
1985    #[serde(default, skip_serializing_if = "is_default")]
1986    pub filter_subject: Option<String>,
1987    /// Optional config for sourcing streams from another prefix, used for cross-account.
1988    #[serde(default, skip_serializing_if = "Option::is_none")]
1989    pub external: Option<External>,
1990    /// Optional config to set a domain, if source is residing in different one.
1991    #[serde(default, skip_serializing_if = "is_default")]
1992    pub domain: Option<String>,
1993    /// Subject transforms for Stream.
1994    #[cfg(feature = "server_2_10")]
1995    #[serde(default, skip_serializing_if = "is_default")]
1996    pub subject_transforms: Vec<SubjectTransform>,
1997
1998    /// Pre-created durable consumer to use for sourcing instead of the
1999    /// auto-managed ephemeral one. Required for full control over the
2000    /// consumer's lifecycle (security, advanced delivery/replay options)
2001    /// when sourcing/mirroring from WorkQueue/Interest streams. Both
2002    /// `name` and `deliver_subject` must be non-empty and valid; the
2003    /// server rejects the config otherwise. See ADR-60.
2004    #[cfg(feature = "server_2_14")]
2005    #[cfg_attr(docsrs, doc(cfg(feature = "server_2_14")))]
2006    #[serde(default, skip_serializing_if = "Option::is_none")]
2007    pub consumer: Option<StreamConsumerSource>,
2008}
2009
2010/// Configures a pre-created durable consumer used for stream
2011/// sourcing/mirroring. See ADR-60.
2012#[cfg(feature = "server_2_14")]
2013#[cfg_attr(docsrs, doc(cfg(feature = "server_2_14")))]
2014#[derive(Clone, Debug, Serialize, Deserialize, Eq, PartialEq, Default)]
2015pub struct StreamConsumerSource {
2016    /// Name of the durable consumer to use for sourcing.
2017    #[serde(default, skip_serializing_if = "is_default")]
2018    pub name: String,
2019    /// Deliver subject of the (push) consumer used for sourcing.
2020    #[serde(default, skip_serializing_if = "is_default")]
2021    pub deliver_subject: String,
2022}
2023
2024#[cfg(feature = "server_2_14")]
2025impl StreamConsumerSource {
2026    /// Build a [`StreamConsumerSource`] with both required fields populated.
2027    /// The server rejects either field empty (`NewJSSourceDurableConsumerCfgInvalidError`).
2028    pub fn new(name: impl Into<String>, deliver_subject: impl Into<String>) -> Self {
2029        Self {
2030            name: name.into(),
2031            deliver_subject: deliver_subject.into(),
2032        }
2033    }
2034}
2035
2036#[derive(Clone, Debug, Serialize, Deserialize, Eq, PartialEq, Default)]
2037pub struct External {
2038    /// Api prefix of external source.
2039    #[serde(rename = "api")]
2040    pub api_prefix: String,
2041    /// Optional configuration of delivery prefix.
2042    #[serde(rename = "deliver", skip_serializing_if = "is_default")]
2043    pub delivery_prefix: Option<String>,
2044}
2045
2046use std::marker::PhantomData;
2047
2048#[derive(Debug, Default)]
2049pub struct Yes;
2050#[derive(Debug, Default)]
2051pub struct No;
2052
2053pub trait ToAssign: Debug {}
2054
2055impl ToAssign for Yes {}
2056impl ToAssign for No {}
2057
2058#[derive(Debug)]
2059pub struct Purge<SEQUENCE, KEEP>
2060where
2061    SEQUENCE: ToAssign,
2062    KEEP: ToAssign,
2063{
2064    inner: PurgeRequest,
2065    sequence_set: PhantomData<SEQUENCE>,
2066    keep_set: PhantomData<KEEP>,
2067    context: Context,
2068    stream_name: String,
2069}
2070
2071impl<SEQUENCE, KEEP> Purge<SEQUENCE, KEEP>
2072where
2073    SEQUENCE: ToAssign,
2074    KEEP: ToAssign,
2075{
2076    /// Adds subject filter to [PurgeRequest]
2077    pub fn filter<T: Into<String>>(mut self, filter: T) -> Purge<SEQUENCE, KEEP> {
2078        self.inner.filter = Some(filter.into());
2079        self
2080    }
2081}
2082
2083impl Purge<No, No> {
2084    pub(crate) fn build<I>(stream: &Stream<I>) -> Purge<No, No> {
2085        Purge {
2086            context: stream.context.clone(),
2087            stream_name: stream.name.clone(),
2088            inner: Default::default(),
2089            sequence_set: PhantomData {},
2090            keep_set: PhantomData {},
2091        }
2092    }
2093}
2094
2095impl<KEEP> Purge<No, KEEP>
2096where
2097    KEEP: ToAssign,
2098{
2099    /// Creates a new [PurgeRequest].
2100    /// `keep` and `sequence` are exclusive, enforced compile time by generics.
2101    pub fn keep(self, keep: u64) -> Purge<No, Yes> {
2102        Purge {
2103            context: self.context.clone(),
2104            stream_name: self.stream_name.clone(),
2105            sequence_set: PhantomData {},
2106            keep_set: PhantomData {},
2107            inner: PurgeRequest {
2108                keep: Some(keep),
2109                ..self.inner
2110            },
2111        }
2112    }
2113}
2114impl<SEQUENCE> Purge<SEQUENCE, No>
2115where
2116    SEQUENCE: ToAssign,
2117{
2118    /// Creates a new [PurgeRequest].
2119    /// `keep` and `sequence` are exclusive, enforces compile time by generics.
2120    pub fn sequence(self, sequence: u64) -> Purge<Yes, No> {
2121        Purge {
2122            context: self.context.clone(),
2123            stream_name: self.stream_name.clone(),
2124            sequence_set: PhantomData {},
2125            keep_set: PhantomData {},
2126            inner: PurgeRequest {
2127                sequence: Some(sequence),
2128                ..self.inner
2129            },
2130        }
2131    }
2132}
2133
2134#[derive(Clone, Debug, PartialEq)]
2135pub enum PurgeErrorKind {
2136    Request,
2137    TimedOut,
2138    JetStream(super::errors::Error),
2139}
2140
2141impl Display for PurgeErrorKind {
2142    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2143        match self {
2144            Self::Request => write!(f, "request failed"),
2145            Self::TimedOut => write!(f, "timed out"),
2146            Self::JetStream(err) => write!(f, "JetStream error: {err}"),
2147        }
2148    }
2149}
2150
2151pub type PurgeError = Error<PurgeErrorKind>;
2152
2153impl<S, K> IntoFuture for Purge<S, K>
2154where
2155    S: ToAssign + std::marker::Send,
2156    K: ToAssign + std::marker::Send,
2157{
2158    type Output = Result<PurgeResponse, PurgeError>;
2159
2160    type IntoFuture = BoxFuture<'static, Result<PurgeResponse, PurgeError>>;
2161
2162    fn into_future(self) -> Self::IntoFuture {
2163        Box::pin(std::future::IntoFuture::into_future(async move {
2164            let request_subject = format!("STREAM.PURGE.{}", self.stream_name);
2165            let response: Response<PurgeResponse> = self
2166                .context
2167                .request(request_subject, &self.inner)
2168                .map_err(|err| match err.kind() {
2169                    RequestErrorKind::TimedOut => PurgeError::new(PurgeErrorKind::TimedOut),
2170                    _ => PurgeError::with_source(PurgeErrorKind::Request, err),
2171                })
2172                .await?;
2173
2174            match response {
2175                Response::Err { error } => Err(PurgeError::new(PurgeErrorKind::JetStream(error))),
2176                Response::Ok(response) => Ok(response),
2177            }
2178        }))
2179    }
2180}
2181
2182#[derive(Deserialize, Debug)]
2183struct ConsumerPage {
2184    total: usize,
2185    consumers: Option<Vec<String>>,
2186}
2187
2188#[derive(Deserialize, Debug)]
2189struct ConsumerInfoPage {
2190    total: usize,
2191    consumers: Option<Vec<super::consumer::Info>>,
2192}
2193
2194type ConsumerNamesErrorKind = StreamsErrorKind;
2195type ConsumerNamesError = StreamsError;
2196type PageRequest = BoxFuture<'static, Result<ConsumerPage, RequestError>>;
2197
2198pub struct ConsumerNames {
2199    context: Context,
2200    stream: String,
2201    offset: usize,
2202    page_request: Option<PageRequest>,
2203    consumers: Vec<String>,
2204    done: bool,
2205}
2206
2207impl futures_util::Stream for ConsumerNames {
2208    type Item = Result<String, ConsumerNamesError>;
2209
2210    fn poll_next(
2211        mut self: Pin<&mut Self>,
2212        cx: &mut std::task::Context<'_>,
2213    ) -> std::task::Poll<Option<Self::Item>> {
2214        match self.page_request.as_mut() {
2215            Some(page) => match page.try_poll_unpin(cx) {
2216                std::task::Poll::Ready(page) => {
2217                    self.page_request = None;
2218                    let page = page.map_err(|err| {
2219                        ConsumerNamesError::with_source(ConsumerNamesErrorKind::Other, err)
2220                    })?;
2221
2222                    if let Some(consumers) = page.consumers {
2223                        self.offset += consumers.len();
2224                        self.consumers = consumers;
2225                        if self.offset >= page.total {
2226                            self.done = true;
2227                        }
2228                        match self.consumers.pop() {
2229                            Some(stream) => Poll::Ready(Some(Ok(stream))),
2230                            None => Poll::Ready(None),
2231                        }
2232                    } else {
2233                        Poll::Ready(None)
2234                    }
2235                }
2236                std::task::Poll::Pending => std::task::Poll::Pending,
2237            },
2238            None => {
2239                if let Some(stream) = self.consumers.pop() {
2240                    Poll::Ready(Some(Ok(stream)))
2241                } else {
2242                    if self.done {
2243                        return Poll::Ready(None);
2244                    }
2245                    let context = self.context.clone();
2246                    let offset = self.offset;
2247                    let stream = self.stream.clone();
2248                    self.page_request = Some(Box::pin(async move {
2249                        match context
2250                            .request(
2251                                format!("CONSUMER.NAMES.{stream}"),
2252                                &json!({
2253                                    "offset": offset,
2254                                }),
2255                            )
2256                            .await?
2257                        {
2258                            Response::Err { error } => Err(RequestError::with_source(
2259                                super::context::RequestErrorKind::Other,
2260                                error,
2261                            )),
2262                            Response::Ok(page) => Ok(page),
2263                        }
2264                    }));
2265                    self.poll_next(cx)
2266                }
2267            }
2268        }
2269    }
2270}
2271
2272pub type ConsumersErrorKind = StreamsErrorKind;
2273pub type ConsumersError = StreamsError;
2274type PageInfoRequest = BoxFuture<'static, Result<ConsumerInfoPage, RequestError>>;
2275
2276pub struct Consumers {
2277    context: Context,
2278    stream: String,
2279    offset: usize,
2280    page_request: Option<PageInfoRequest>,
2281    consumers: Vec<super::consumer::Info>,
2282    done: bool,
2283}
2284
2285impl futures_util::Stream for Consumers {
2286    type Item = Result<super::consumer::Info, ConsumersError>;
2287
2288    fn poll_next(
2289        mut self: Pin<&mut Self>,
2290        cx: &mut std::task::Context<'_>,
2291    ) -> std::task::Poll<Option<Self::Item>> {
2292        match self.page_request.as_mut() {
2293            Some(page) => match page.try_poll_unpin(cx) {
2294                std::task::Poll::Ready(page) => {
2295                    self.page_request = None;
2296                    let page = page.map_err(|err| {
2297                        ConsumersError::with_source(ConsumersErrorKind::Other, err)
2298                    })?;
2299                    if let Some(consumers) = page.consumers {
2300                        self.offset += consumers.len();
2301                        self.consumers = consumers;
2302                        if self.offset >= page.total {
2303                            self.done = true;
2304                        }
2305                        match self.consumers.pop() {
2306                            Some(consumer) => Poll::Ready(Some(Ok(consumer))),
2307                            None => Poll::Ready(None),
2308                        }
2309                    } else {
2310                        Poll::Ready(None)
2311                    }
2312                }
2313                std::task::Poll::Pending => std::task::Poll::Pending,
2314            },
2315            None => {
2316                if let Some(stream) = self.consumers.pop() {
2317                    Poll::Ready(Some(Ok(stream)))
2318                } else {
2319                    if self.done {
2320                        return Poll::Ready(None);
2321                    }
2322                    let context = self.context.clone();
2323                    let offset = self.offset;
2324                    let stream = self.stream.clone();
2325                    self.page_request = Some(Box::pin(async move {
2326                        match context
2327                            .request(
2328                                format!("CONSUMER.LIST.{stream}"),
2329                                &json!({
2330                                    "offset": offset,
2331                                }),
2332                            )
2333                            .await?
2334                        {
2335                            Response::Err { error } => Err(RequestError::with_source(
2336                                super::context::RequestErrorKind::Other,
2337                                error,
2338                            )),
2339                            Response::Ok(page) => Ok(page),
2340                        }
2341                    }));
2342                    self.poll_next(cx)
2343                }
2344            }
2345        }
2346    }
2347}
2348
2349#[derive(Clone, Debug, PartialEq)]
2350pub enum LastRawMessageErrorKind {
2351    NoMessageFound,
2352    InvalidSubject,
2353    JetStream(super::errors::Error),
2354    Other,
2355}
2356
2357impl Display for LastRawMessageErrorKind {
2358    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2359        match self {
2360            Self::NoMessageFound => write!(f, "no message found"),
2361            Self::InvalidSubject => write!(f, "invalid subject"),
2362            Self::Other => write!(f, "failed to get last raw message"),
2363            Self::JetStream(err) => write!(f, "JetStream error: {err}"),
2364        }
2365    }
2366}
2367
2368pub type LastRawMessageError = Error<LastRawMessageErrorKind>;
2369pub type RawMessageErrorKind = LastRawMessageErrorKind;
2370pub type RawMessageError = LastRawMessageError;
2371
2372#[derive(Clone, Debug, PartialEq)]
2373pub enum ConsumerErrorKind {
2374    //TODO: get last should have timeout, which should be mapped here.
2375    TimedOut,
2376    Request,
2377    InvalidConsumerType,
2378    InvalidName,
2379    JetStream(super::errors::Error),
2380    Other,
2381}
2382
2383impl Display for ConsumerErrorKind {
2384    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2385        match self {
2386            Self::TimedOut => write!(f, "timed out"),
2387            Self::Request => write!(f, "request failed"),
2388            Self::JetStream(err) => write!(f, "JetStream error: {err}"),
2389            Self::Other => write!(f, "consumer error"),
2390            Self::InvalidConsumerType => write!(f, "invalid consumer type"),
2391            Self::InvalidName => write!(f, "invalid consumer name"),
2392        }
2393    }
2394}
2395
2396pub type ConsumerError = Error<ConsumerErrorKind>;
2397
2398#[cfg(feature = "server_2_14")]
2399#[cfg_attr(docsrs, doc(cfg(feature = "server_2_14")))]
2400#[derive(Clone, Debug, PartialEq)]
2401pub enum ConsumerResetErrorKind {
2402    TimedOut,
2403    Request,
2404    /// Stream or consumer does not exist.
2405    ///
2406    /// Surfaced when the server replies with `CONSUMER_NOT_FOUND` /
2407    /// `STREAM_NOT_FOUND`, or via core NATS `NoResponders` if the JS API
2408    /// has no handler for the subject.
2409    NotFound,
2410    /// Reset request violates the consumer's `DeliverPolicy` constraints
2411    /// (e.g. seq below `OptStartSeq`, or non-zero seq with a `DeliverPolicy`
2412    /// other than `All` / `ByStartSequence` / `ByStartTime`).
2413    InvalidReset,
2414    JetStream(super::errors::Error),
2415}
2416
2417#[cfg(feature = "server_2_14")]
2418#[cfg_attr(docsrs, doc(cfg(feature = "server_2_14")))]
2419impl Display for ConsumerResetErrorKind {
2420    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2421        match self {
2422            Self::TimedOut => write!(f, "timed out"),
2423            Self::Request => write!(f, "request failed"),
2424            Self::NotFound => write!(f, "stream or consumer not found"),
2425            Self::InvalidReset => write!(f, "invalid reset"),
2426            Self::JetStream(err) => write!(f, "JetStream error: {err}"),
2427        }
2428    }
2429}
2430
2431#[cfg(feature = "server_2_14")]
2432pub type ConsumerResetError = Error<ConsumerResetErrorKind>;
2433
2434#[cfg(feature = "server_2_14")]
2435impl From<super::errors::Error> for ConsumerResetError {
2436    fn from(err: super::errors::Error) -> Self {
2437        match err.error_code() {
2438            super::errors::ErrorCode::CONSUMER_INVALID_RESET => {
2439                ConsumerResetError::new(ConsumerResetErrorKind::InvalidReset)
2440            }
2441            super::errors::ErrorCode::CONSUMER_NOT_FOUND
2442            | super::errors::ErrorCode::STREAM_NOT_FOUND => {
2443                ConsumerResetError::new(ConsumerResetErrorKind::NotFound)
2444            }
2445            _ => ConsumerResetError::new(ConsumerResetErrorKind::JetStream(err)),
2446        }
2447    }
2448}
2449
2450#[cfg(feature = "server_2_14")]
2451impl From<super::context::RequestError> for ConsumerResetError {
2452    fn from(err: super::context::RequestError) -> Self {
2453        match err.kind() {
2454            RequestErrorKind::TimedOut => ConsumerResetError::new(ConsumerResetErrorKind::TimedOut),
2455            RequestErrorKind::NoResponders => {
2456                ConsumerResetError::new(ConsumerResetErrorKind::NotFound)
2457            }
2458            _ => ConsumerResetError::with_source(ConsumerResetErrorKind::Request, err),
2459        }
2460    }
2461}
2462
2463#[derive(Clone, Debug, PartialEq)]
2464pub enum ConsumerCreateStrictErrorKind {
2465    //TODO: get last should have timeout, which should be mapped here.
2466    TimedOut,
2467    Request,
2468    InvalidConsumerType,
2469    InvalidName,
2470    AlreadyExists,
2471    JetStream(super::errors::Error),
2472    Other,
2473}
2474
2475impl Display for ConsumerCreateStrictErrorKind {
2476    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2477        match self {
2478            Self::TimedOut => write!(f, "timed out"),
2479            Self::Request => write!(f, "request failed"),
2480            Self::JetStream(err) => write!(f, "JetStream error: {err}"),
2481            Self::Other => write!(f, "consumer error"),
2482            Self::InvalidConsumerType => write!(f, "invalid consumer type"),
2483            Self::InvalidName => write!(f, "invalid consumer name"),
2484            Self::AlreadyExists => write!(f, "consumer already exists"),
2485        }
2486    }
2487}
2488
2489pub type ConsumerCreateStrictError = Error<ConsumerCreateStrictErrorKind>;
2490
2491#[derive(Clone, Debug, PartialEq)]
2492pub enum ConsumerUpdateErrorKind {
2493    //TODO: get last should have timeout, which should be mapped here.
2494    TimedOut,
2495    Request,
2496    InvalidConsumerType,
2497    InvalidName,
2498    DoesNotExist,
2499    JetStream(super::errors::Error),
2500    Other,
2501}
2502
2503impl Display for ConsumerUpdateErrorKind {
2504    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2505        match self {
2506            Self::TimedOut => write!(f, "timed out"),
2507            Self::Request => write!(f, "request failed"),
2508            Self::JetStream(err) => write!(f, "JetStream error: {err}"),
2509            Self::Other => write!(f, "consumer error"),
2510            Self::InvalidConsumerType => write!(f, "invalid consumer type"),
2511            Self::InvalidName => write!(f, "invalid consumer name"),
2512            Self::DoesNotExist => write!(f, "consumer does not exist"),
2513        }
2514    }
2515}
2516
2517pub type ConsumerUpdateError = Error<ConsumerUpdateErrorKind>;
2518
2519impl From<super::errors::Error> for ConsumerError {
2520    fn from(err: super::errors::Error) -> Self {
2521        ConsumerError::new(ConsumerErrorKind::JetStream(err))
2522    }
2523}
2524impl From<super::errors::Error> for ConsumerCreateStrictError {
2525    fn from(err: super::errors::Error) -> Self {
2526        if err.error_code() == super::errors::ErrorCode::CONSUMER_ALREADY_EXISTS {
2527            ConsumerCreateStrictError::new(ConsumerCreateStrictErrorKind::AlreadyExists)
2528        } else {
2529            ConsumerCreateStrictError::new(ConsumerCreateStrictErrorKind::JetStream(err))
2530        }
2531    }
2532}
2533impl From<super::errors::Error> for ConsumerUpdateError {
2534    fn from(err: super::errors::Error) -> Self {
2535        if err.error_code() == super::errors::ErrorCode::CONSUMER_DOES_NOT_EXIST {
2536            ConsumerUpdateError::new(ConsumerUpdateErrorKind::DoesNotExist)
2537        } else {
2538            ConsumerUpdateError::new(ConsumerUpdateErrorKind::JetStream(err))
2539        }
2540    }
2541}
2542impl From<ConsumerError> for ConsumerUpdateError {
2543    fn from(err: ConsumerError) -> Self {
2544        match err.kind() {
2545            ConsumerErrorKind::JetStream(err) => {
2546                if err.error_code() == super::errors::ErrorCode::CONSUMER_DOES_NOT_EXIST {
2547                    ConsumerUpdateError::new(ConsumerUpdateErrorKind::DoesNotExist)
2548                } else {
2549                    ConsumerUpdateError::new(ConsumerUpdateErrorKind::JetStream(err))
2550                }
2551            }
2552            ConsumerErrorKind::Request => {
2553                ConsumerUpdateError::new(ConsumerUpdateErrorKind::Request)
2554            }
2555            ConsumerErrorKind::TimedOut => {
2556                ConsumerUpdateError::new(ConsumerUpdateErrorKind::TimedOut)
2557            }
2558            ConsumerErrorKind::InvalidConsumerType => {
2559                ConsumerUpdateError::new(ConsumerUpdateErrorKind::InvalidConsumerType)
2560            }
2561            ConsumerErrorKind::InvalidName => {
2562                ConsumerUpdateError::new(ConsumerUpdateErrorKind::InvalidName)
2563            }
2564            ConsumerErrorKind::Other => ConsumerUpdateError::new(ConsumerUpdateErrorKind::Other),
2565        }
2566    }
2567}
2568
2569impl From<ConsumerError> for ConsumerCreateStrictError {
2570    fn from(err: ConsumerError) -> Self {
2571        match err.kind() {
2572            ConsumerErrorKind::JetStream(err) => {
2573                if err.error_code() == super::errors::ErrorCode::CONSUMER_ALREADY_EXISTS {
2574                    ConsumerCreateStrictError::new(ConsumerCreateStrictErrorKind::AlreadyExists)
2575                } else {
2576                    ConsumerCreateStrictError::new(ConsumerCreateStrictErrorKind::JetStream(err))
2577                }
2578            }
2579            ConsumerErrorKind::Request => {
2580                ConsumerCreateStrictError::new(ConsumerCreateStrictErrorKind::Request)
2581            }
2582            ConsumerErrorKind::TimedOut => {
2583                ConsumerCreateStrictError::new(ConsumerCreateStrictErrorKind::TimedOut)
2584            }
2585            ConsumerErrorKind::InvalidConsumerType => {
2586                ConsumerCreateStrictError::new(ConsumerCreateStrictErrorKind::InvalidConsumerType)
2587            }
2588            ConsumerErrorKind::InvalidName => {
2589                ConsumerCreateStrictError::new(ConsumerCreateStrictErrorKind::InvalidName)
2590            }
2591            ConsumerErrorKind::Other => {
2592                ConsumerCreateStrictError::new(ConsumerCreateStrictErrorKind::Other)
2593            }
2594        }
2595    }
2596}
2597
2598impl From<super::context::RequestError> for ConsumerError {
2599    fn from(err: super::context::RequestError) -> Self {
2600        match err.kind() {
2601            RequestErrorKind::TimedOut => ConsumerError::new(ConsumerErrorKind::TimedOut),
2602            _ => ConsumerError::with_source(ConsumerErrorKind::Request, err),
2603        }
2604    }
2605}
2606impl From<super::context::RequestError> for ConsumerUpdateError {
2607    fn from(err: super::context::RequestError) -> Self {
2608        match err.kind() {
2609            RequestErrorKind::TimedOut => {
2610                ConsumerUpdateError::new(ConsumerUpdateErrorKind::TimedOut)
2611            }
2612            _ => ConsumerUpdateError::with_source(ConsumerUpdateErrorKind::Request, err),
2613        }
2614    }
2615}
2616impl From<super::context::RequestError> for ConsumerCreateStrictError {
2617    fn from(err: super::context::RequestError) -> Self {
2618        match err.kind() {
2619            RequestErrorKind::TimedOut => {
2620                ConsumerCreateStrictError::new(ConsumerCreateStrictErrorKind::TimedOut)
2621            }
2622            _ => {
2623                ConsumerCreateStrictError::with_source(ConsumerCreateStrictErrorKind::Request, err)
2624            }
2625        }
2626    }
2627}
2628
2629#[derive(Debug, Serialize, Default)]
2630pub struct DirectGetRequest {
2631    #[serde(rename = "seq", skip_serializing_if = "Option::is_none")]
2632    sequence: Option<u64>,
2633    #[serde(rename = "last_by_subj", skip_serializing)]
2634    last_by_subject: Option<String>,
2635    #[serde(rename = "next_by_subj", skip_serializing_if = "Option::is_none")]
2636    next_by_subject: Option<String>,
2637}
2638
2639/// Marker type indicating that headers should be included in the response.
2640pub struct WithHeaders;
2641
2642/// Marker type indicating that headers should be excluded from the response.
2643pub struct WithoutHeaders;
2644
2645/// Trait for converting a Message response into the appropriate return type.
2646trait DirectGetResponse: Sized {
2647    fn from_message(message: crate::Message) -> Result<Self, DirectGetError>;
2648}
2649
2650impl DirectGetResponse for StreamMessage {
2651    fn from_message(message: crate::Message) -> Result<Self, DirectGetError> {
2652        StreamMessage::try_from(message).map_err(Into::into)
2653    }
2654}
2655
2656impl DirectGetResponse for StreamValue {
2657    fn from_message(message: crate::Message) -> Result<Self, DirectGetError> {
2658        Ok(StreamValue {
2659            data: message.payload,
2660        })
2661    }
2662}
2663
2664pub struct DirectGetBuilder<T = WithHeaders> {
2665    context: Context,
2666    stream_name: String,
2667    request: DirectGetRequest,
2668    _phantom: std::marker::PhantomData<T>,
2669}
2670
2671impl DirectGetBuilder<WithHeaders> {
2672    fn new(context: Context, stream_name: String) -> DirectGetBuilder<WithHeaders> {
2673        DirectGetBuilder {
2674            context,
2675            stream_name,
2676            request: DirectGetRequest::default(),
2677            _phantom: std::marker::PhantomData,
2678        }
2679    }
2680}
2681
2682impl<T> DirectGetBuilder<T> {
2683    /// Internal method to send the direct get request and convert to the appropriate type.
2684    async fn send_internal<R: DirectGetResponse>(&self) -> Result<R, DirectGetError> {
2685        // When last_by_subject is used, the subject is embedded in the URL and we should send an empty payload
2686        // to match the NATS protocol expectation (similar to nats.go implementation)
2687        let payload = if self.request.last_by_subject.is_some() {
2688            Bytes::new()
2689        } else {
2690            serde_json::to_vec(&self.request).map(Bytes::from)?
2691        };
2692
2693        let request_subject = if let Some(ref subject) = self.request.last_by_subject {
2694            format!(
2695                "{}.DIRECT.GET.{}.{}",
2696                self.context.prefix, self.stream_name, subject
2697            )
2698        } else {
2699            format!("{}.DIRECT.GET.{}", self.context.prefix, self.stream_name)
2700        };
2701
2702        let response = self
2703            .context
2704            .client
2705            .request(request_subject, payload)
2706            .await?;
2707
2708        // Check for error status
2709        if let Some(status) = response.status {
2710            if let Some(ref description) = response.description {
2711                match status {
2712                    StatusCode::NOT_FOUND => {
2713                        return Err(DirectGetError::new(DirectGetErrorKind::NotFound))
2714                    }
2715                    // 408 is used in Direct Message for bad/empty payload.
2716                    StatusCode::TIMEOUT => {
2717                        return Err(DirectGetError::new(DirectGetErrorKind::InvalidSubject))
2718                    }
2719                    _ => {
2720                        return Err(DirectGetError::new(DirectGetErrorKind::ErrorResponse(
2721                            status,
2722                            description.to_string(),
2723                        )));
2724                    }
2725                }
2726            }
2727        }
2728
2729        R::from_message(response)
2730    }
2731
2732    /// Sets the sequence for the direct get request.
2733    pub fn sequence(mut self, seq: u64) -> Self {
2734        self.request.sequence = Some(seq);
2735        self
2736    }
2737
2738    /// Sets the last_by_subject for the direct get request.
2739    pub fn last_by_subject<S: Into<String>>(mut self, subject: S) -> Self {
2740        self.request.last_by_subject = Some(subject.into());
2741        self
2742    }
2743
2744    /// Sets the next_by_subject for the direct get request.
2745    pub fn next_by_subject<S: Into<String>>(mut self, subject: S) -> Self {
2746        self.request.next_by_subject = Some(subject.into());
2747        self
2748    }
2749}
2750
2751impl DirectGetBuilder<WithHeaders> {
2752    /// Sends the get request and returns a StreamMessage with headers.
2753    pub async fn send(self) -> Result<StreamMessage, DirectGetError> {
2754        self.send_internal::<StreamMessage>().await
2755    }
2756}
2757
2758impl DirectGetBuilder<WithoutHeaders> {
2759    /// Sends the get request and returns only the payload bytes without headers.
2760    pub async fn send(self) -> Result<StreamValue, DirectGetError> {
2761        self.send_internal::<StreamValue>().await
2762    }
2763}
2764
2765pub struct StreamValue {
2766    pub data: Bytes,
2767}
2768
2769#[derive(Debug, Serialize, Default)]
2770pub struct RawMessageRequest {
2771    #[serde(rename = "seq", skip_serializing_if = "Option::is_none")]
2772    sequence: Option<u64>,
2773    #[serde(rename = "last_by_subj", skip_serializing_if = "Option::is_none")]
2774    last_by_subject: Option<String>,
2775    #[serde(rename = "next_by_subj", skip_serializing_if = "Option::is_none")]
2776    next_by_subject: Option<String>,
2777}
2778
2779/// Trait for converting a RawMessage response into the appropriate return type.
2780trait RawMessageResponse: Sized {
2781    fn from_raw_message(message: RawMessage) -> Result<Self, RawMessageError>;
2782}
2783
2784impl RawMessageResponse for StreamMessage {
2785    fn from_raw_message(message: RawMessage) -> Result<Self, RawMessageError> {
2786        StreamMessage::try_from(message)
2787            .map_err(|err| RawMessageError::with_source(RawMessageErrorKind::Other, err))
2788    }
2789}
2790
2791impl RawMessageResponse for StreamValue {
2792    fn from_raw_message(message: RawMessage) -> Result<Self, RawMessageError> {
2793        use base64::engine::general_purpose::STANDARD;
2794        use base64::Engine;
2795
2796        let decoded_payload = STANDARD.decode(message.payload).map_err(|err| {
2797            RawMessageError::with_source(
2798                RawMessageErrorKind::Other,
2799                Box::new(std::io::Error::other(err)),
2800            )
2801        })?;
2802
2803        Ok(StreamValue {
2804            data: decoded_payload.into(),
2805        })
2806    }
2807}
2808
2809pub struct RawMessageBuilder<T = WithHeaders> {
2810    context: Context,
2811    stream_name: String,
2812    request: RawMessageRequest,
2813    _phantom: std::marker::PhantomData<T>,
2814}
2815
2816impl RawMessageBuilder<WithHeaders> {
2817    fn new(context: Context, stream_name: String) -> Self {
2818        RawMessageBuilder {
2819            context,
2820            stream_name,
2821            request: RawMessageRequest::default(),
2822            _phantom: std::marker::PhantomData,
2823        }
2824    }
2825}
2826
2827impl<T> RawMessageBuilder<T> {
2828    /// Internal method to send the raw message request and convert to the appropriate type.
2829    async fn send_internal<R: RawMessageResponse>(&self) -> Result<R, RawMessageError> {
2830        // Validate subjects
2831        for subject in [&self.request.last_by_subject, &self.request.next_by_subject]
2832            .into_iter()
2833            .flatten()
2834        {
2835            if !is_valid_subject(subject) {
2836                return Err(RawMessageError::new(RawMessageErrorKind::InvalidSubject));
2837            }
2838        }
2839
2840        let subject = format!("STREAM.MSG.GET.{}", self.stream_name);
2841
2842        let response: Response<GetRawMessage> = self
2843            .context
2844            .request(subject, &self.request)
2845            .map_err(|err| RawMessageError::with_source(RawMessageErrorKind::Other, err))
2846            .await?;
2847
2848        match response {
2849            Response::Err { error } => {
2850                if error.error_code() == ErrorCode::NO_MESSAGE_FOUND {
2851                    Err(RawMessageError::new(RawMessageErrorKind::NoMessageFound))
2852                } else {
2853                    Err(RawMessageError::new(RawMessageErrorKind::JetStream(error)))
2854                }
2855            }
2856            Response::Ok(value) => R::from_raw_message(value.message),
2857        }
2858    }
2859
2860    /// Sets the sequence for the raw message request.
2861    pub fn sequence(mut self, seq: u64) -> Self {
2862        self.request.sequence = Some(seq);
2863        self
2864    }
2865
2866    /// Sets the last_by_subject for the raw message request.
2867    pub fn last_by_subject<S: Into<String>>(mut self, subject: S) -> Self {
2868        self.request.last_by_subject = Some(subject.into());
2869        self
2870    }
2871
2872    /// Sets the next_by_subject for the raw message request.
2873    pub fn next_by_subject<S: Into<String>>(mut self, subject: S) -> Self {
2874        self.request.next_by_subject = Some(subject.into());
2875        self
2876    }
2877}
2878
2879impl RawMessageBuilder<WithHeaders> {
2880    /// Sends the raw message request and returns a StreamMessage with headers.
2881    pub async fn send(self) -> Result<StreamMessage, RawMessageError> {
2882        self.send_internal::<StreamMessage>().await
2883    }
2884}
2885
2886impl RawMessageBuilder<WithoutHeaders> {
2887    /// Sends the raw message request and returns only the payload as StreamValue.
2888    pub async fn send(self) -> Result<StreamValue, RawMessageError> {
2889        self.send_internal::<StreamValue>().await
2890    }
2891}
2892
2893#[cfg(test)]
2894mod tests {
2895    use super::*;
2896
2897    #[test]
2898    fn consumer_limits_de() {
2899        let config = Config {
2900            ..Default::default()
2901        };
2902
2903        let roundtrip: Config = {
2904            let ser = serde_json::to_string(&config).unwrap();
2905            serde_json::from_str(&ser).unwrap()
2906        };
2907        assert_eq!(config, roundtrip);
2908    }
2909}