2024-05-10 22:34:32 -03:00

124 lines
3.3 KiB
Rust

use {eyre::Result, redis::Client, std::fmt::Debug};
pub mod publish;
pub mod subscribe;
pub(crate) const KEY_PREFIX: &str = "rustler";
/// creates a message redis key from a prefix and a key
pub(crate) fn key<T: AsRef<str>, K: AsRef<str>>(prefix: T, key: K) -> String {
let prefix = prefix.as_ref();
let key = key.as_ref();
match prefix.is_empty() {
true => key.to_string(),
false => format!("{}:{}", prefix, key),
}
}
/// represents a pub or sub handler that can be prefixed
pub trait PrefixedPubSub {
fn get_prefix(&self) -> String;
fn set_prefix(&mut self, prefix: &str) -> &mut Self;
fn with_prefix(&mut self, prefix: &str) -> &mut Self {
self.set_prefix(prefix);
self
}
fn without_prefix(&mut self) -> &mut Self {
self.set_prefix("");
self
}
}
/// 🐎 » represents a an entity that can provide a redis client
pub trait RedisClient {
fn get_client(&self) -> Result<Client>;
}
impl RedisClient for Client {
fn get_client(&self) -> Result<Client> {
let redis = self.clone();
Ok(redis)
}
}
impl RedisClient for &str {
fn get_client(&self) -> Result<Client> {
let redis = Client::open(*self)?;
Ok(redis)
}
}
impl RedisClient for String {
fn get_client(&self) -> Result<Client> {
let redis = Client::open(self.as_str())?;
Ok(redis)
}
}
/// 🐎 » represents a value that can be serialized to a redis value
pub trait ToRedisVal {
fn to_redis_val(&self) -> Vec<(String, String)>;
}
/// 🐎 » represents a value that can be serialized to a redis key
pub trait ToRedisKey {
fn to_redis_key(&self) -> String;
}
/// 🐎 » represents a value that can be serialized to and from a redis message
pub trait ToFromRedisMessage {
fn as_message(&self) -> String;
fn from_message<T: AsRef<str>>(msg: T) -> Self;
}
/// 🐎 » supertrait combining all redis object traits + debug + send + sync + 'static
pub trait RedisMessage:
ToRedisVal + ToRedisKey + ToFromRedisMessage + Debug + Clone + Send + Sync + PartialEq + 'static
{
}
/// 🐎 » **publisher**: create bus publisher
///
/// **Arguments**
/// - `redis` - a redis client or a redis connection string
///
/// **Returns**
/// - a new `Publisher` instance
pub async fn publisher<RM: RedisMessage, RC: RedisClient>(
redis: &RC,
) -> Result<publish::Publisher<RM>> {
publish::Publisher::new(redis).await
}
/// 🐎 » **subscriber**: create bus subscriber
///
/// **Arguments**
/// - `redis` - a redis client or a redis connection string
///
/// **Returns**
/// - a new `Subscriber` instance
pub async fn subscriber<RM: RedisMessage, RC: RedisClient>(
redis: &RC,
) -> Result<subscribe::Subscriber<RM>> {
subscribe::Subscriber::new(redis).await
}
/// 🐎 » **pubsub*: create bus publisher and subscriber
///
/// **Arguments**
/// - `redis` - a redis client or a redis connection string
///
/// **Returns**
/// - a tuple containing a `Publisher` and a `Subscriber` instance
pub async fn pubsub<RO: RedisMessage, T: RedisClient>(
redis: &T,
) -> Result<(publish::Publisher<RO>, subscribe::Subscriber<RO>)> {
let publisher = publish::Publisher::new(redis).await?;
let subscriber = subscribe::Subscriber::new(redis).await?;
Ok((publisher, subscriber))
}