use std::{marker::PhantomData, sync::Arc};
use async_nats::ServerAddr;
use serde::{de::DeserializeOwned, Serialize};
use crate::{
codec::CodecType,
error::{Error, Result},
jetstream::context::JetStreamContext,
publisher::Publisher,
subscriber::Subscriber,
};
#[derive(Clone)]
pub struct Client<C: CodecType> {
inner: Arc<async_nats::Client>,
_codec: PhantomData<C>,
}
impl<C: CodecType> Client<C> {
pub async fn connect<A: ToServerAddrs>(addrs: A) -> Result<Self> {
let client = async_nats::connect(addrs).await?;
Ok(Self {
inner: Arc::new(client),
_codec: PhantomData,
})
}
pub async fn connect_with_options<A: ToServerAddrs>(
addrs: A,
options: async_nats::ConnectOptions,
) -> Result<Self> {
let client = options.connect(addrs).await?;
Ok(Self {
inner: Arc::new(client),
_codec: PhantomData,
})
}
pub fn inner(&self) -> &async_nats::Client {
&self.inner
}
pub async fn publish<T: Serialize>(&self, subject: &str, message: &T) -> Result<()> {
let data = C::encode(message)?;
self.inner
.publish(subject.to_string(), data.into())
.await?;
Ok(())
}
pub async fn request<T: Serialize, R: DeserializeOwned>(
&self,
subject: &str,
message: &T,
) -> Result<R> {
let data = C::encode(message)?;
let response = self.inner.request(subject.to_string(), data.into()).await?;
C::decode(&response.payload)
}
pub async fn publish_with_reply<T: Serialize>(
&self,
subject: &str,
reply: &str,
message: &T,
) -> Result<()> {
let data = C::encode(message)?;
self.inner
.publish_with_reply(subject.to_string(), reply.to_string(), data.into())
.await?;
Ok(())
}
pub async fn subscribe<T: DeserializeOwned>(&self, subject: &str) -> Result<Subscriber<T, C>> {
let inner = self.inner.subscribe(subject.to_string()).await?;
Ok(Subscriber::new(inner))
}
pub async fn queue_subscribe<T: DeserializeOwned>(
&self,
subject: &str,
queue_group: &str,
) -> Result<Subscriber<T, C>> {
let inner = self
.inner
.queue_subscribe(subject.to_string(), queue_group.to_string())
.await?;
Ok(Subscriber::new(inner))
}
pub fn publisher<T: Serialize>(&self, subject: &str) -> Publisher<T, C> {
Publisher::new(self.inner.clone(), subject.to_string())
}
pub fn jetstream(&self) -> JetStreamContext<C> {
JetStreamContext::new(async_nats::jetstream::new((*self.inner).clone()))
}
pub fn jetstream_with_domain(&self, domain: &str) -> JetStreamContext<C> {
JetStreamContext::new(async_nats::jetstream::with_domain(
(*self.inner).clone(),
domain,
))
}
pub fn jetstream_with_prefix(&self, prefix: &str) -> JetStreamContext<C> {
JetStreamContext::new(async_nats::jetstream::with_prefix(
(*self.inner).clone(),
prefix,
))
}
pub async fn flush(&self) -> Result<()> {
self.inner
.flush()
.await
.map_err(|e| Error::Nats(e.into()))
}
}
pub trait ToServerAddrs: async_nats::ToServerAddrs {}
impl ToServerAddrs for &str {}
impl ToServerAddrs for String {}
impl ToServerAddrs for &String {}
impl ToServerAddrs for ServerAddr {}
impl ToServerAddrs for &ServerAddr {}
impl ToServerAddrs for Vec<ServerAddr> {}
impl ToServerAddrs for &[ServerAddr] {}