grafbase_sdk/host_io/
nats.rs

1//! Client interface for interacting with NATS messaging system
2//!
3//! This module provides a high-level client for connecting to and interacting with NATS servers.
4//! It supports both authenticated and unauthenticated connections to one or more NATS servers.
5
6use crate::wit::NatsAuth;
7
8/// A client for interacting with NATS servers
9pub struct NatsClient {
10    inner: crate::wit::NatsClient,
11}
12
13impl NatsClient {
14    /// Publishes a message to the specified NATS subject
15    ///
16    /// # Arguments
17    ///
18    /// * `subject` - The NATS subject to publish to
19    /// * `payload` - The message payload as a byte slice
20    ///
21    /// # Returns
22    ///
23    /// Result indicating success or an error if the publish fails
24    pub fn publish<S>(&self, subject: &str, payload: &S) -> Result<(), Box<dyn std::error::Error>>
25    where
26        S: serde::Serialize,
27    {
28        Ok(self.inner.publish(subject, &serde_json::to_vec(payload).unwrap())?)
29    }
30
31    /// Subscribes to messages on the specified NATS subject
32    ///
33    /// # Arguments
34    ///
35    /// * `subject` - The NATS subject to subscribe to
36    ///
37    /// # Returns
38    ///
39    /// Result containing the subscription or an error if subscription fails
40    pub fn subscribe(&self, subject: &str) -> Result<NatsSubscriber, Box<dyn std::error::Error>> {
41        Ok(self.inner.subscribe(subject).map(Into::into)?)
42    }
43}
44
45/// A subscription to a NATS subject that receives messages published to that subject
46pub struct NatsSubscriber {
47    inner: crate::wit::NatsSubscriber,
48}
49
50impl From<crate::wit::NatsSubscriber> for NatsSubscriber {
51    fn from(inner: crate::wit::NatsSubscriber) -> Self {
52        NatsSubscriber { inner }
53    }
54}
55
56impl NatsSubscriber {
57    /// Gets the next message from the subscription
58    ///
59    /// # Returns
60    ///
61    /// Result containing the next message or an error if retrieval fails
62    pub fn next(&self) -> Option<NatsMessage> {
63        self.inner.next().map(Into::into)
64    }
65}
66
67/// A message received from a NATS subscription containing the payload data
68pub struct NatsMessage {
69    inner: crate::wit::NatsMessage,
70}
71
72impl From<crate::wit::NatsMessage> for NatsMessage {
73    fn from(inner: crate::wit::NatsMessage) -> Self {
74        NatsMessage { inner }
75    }
76}
77
78impl NatsMessage {
79    /// Gets the payload data of the message
80    ///
81    /// # Returns
82    ///
83    /// Result containing the payload data or an error if retrieval fails
84    pub fn payload<S>(&self) -> anyhow::Result<S>
85    where
86        S: for<'de> serde::Deserialize<'de>,
87    {
88        Ok(serde_json::from_slice(&self.inner.payload)?)
89    }
90
91    /// Gets the subject of the message
92    ///
93    /// # Returns
94    ///
95    /// The NATS subject this message was published to
96    pub fn subject(&self) -> &str {
97        &self.inner.subject
98    }
99}
100
101/// Connects to one or more NATS servers
102///
103/// # Arguments
104///
105/// * `servers` - Iterator of server addresses to connect to
106///
107/// # Returns
108///
109/// Result containing the connected NATS client or an error if connection fails
110pub fn connect(servers: impl IntoIterator<Item = impl ToString>) -> Result<NatsClient, Box<dyn std::error::Error>> {
111    let servers: Vec<_> = servers.into_iter().map(|s| s.to_string()).collect();
112    let inner = crate::wit::NatsClient::connect(&servers, None)?;
113
114    Ok(NatsClient { inner })
115}
116
117/// Connects to one or more NATS servers with authentication
118///
119/// # Arguments
120///
121/// * `servers` - Iterator of server addresses to connect to
122/// * `auth` - Authentication credentials for connecting to the servers
123///
124/// # Returns
125///
126/// Result containing the connected NATS client or an error if connection fails
127pub fn connect_with_auth(
128    servers: impl IntoIterator<Item = impl ToString>,
129    auth: &NatsAuth,
130) -> Result<NatsClient, Box<dyn std::error::Error>> {
131    let servers: Vec<_> = servers.into_iter().map(|s| s.to_string()).collect();
132    let inner = crate::wit::NatsClient::connect(&servers, Some(auth))?;
133
134    Ok(NatsClient { inner })
135}