use async_trait::async_trait;
use serde::{Serialize, de::DeserializeOwned};
use crate::Result;
use crate::cache::Cache;
use crate::job_queue::JobQueue;
use crate::publisher::Publisher;
use crate::types::Priority;
#[async_trait]
pub trait CacheExt: Cache {
async fn set_typed<T: Serialize + Send + Sync>(
&self,
key: &str,
value: &T,
ttl_seconds: Option<i32>,
) -> Result<()> {
let json = serde_json::to_value(value)?;
self.set(key, &json, ttl_seconds).await
}
async fn get_typed<T: DeserializeOwned>(&self, key: &str) -> Result<Option<T>> {
match self.get(key).await? {
Some(value) => Ok(Some(serde_json::from_value(value)?)),
None => Ok(None),
}
}
async fn mget_typed<T: DeserializeOwned>(
&self,
keys: &[&str],
) -> Result<Vec<(String, Option<T>)>> {
let raw = self.mget(keys).await?;
let mut results = Vec::with_capacity(raw.len());
for (key, value) in raw {
let parsed = match value {
Some(v) => Some(serde_json::from_value(v)?),
None => None,
};
results.push((key, parsed));
}
Ok(results)
}
}
impl<T: Cache + ?Sized> CacheExt for T {}
#[async_trait]
pub trait JobQueueExt: JobQueue {
async fn push_typed<T: Serialize + Send + Sync>(
&self,
queue_name: &str,
payload: &T,
priority: Priority,
) -> Result<String> {
let json = serde_json::to_value(payload)?;
self.push(queue_name, &json, priority).await
}
async fn push_typed_with_options<T: Serialize + Send + Sync>(
&self,
queue_name: &str,
payload: &T,
priority: Priority,
delay_seconds: i32,
max_attempts: i32,
) -> Result<String> {
let json = serde_json::to_value(payload)?;
self.push_with_options(queue_name, &json, priority, delay_seconds, max_attempts)
.await
}
async fn pop_typed<T: DeserializeOwned>(
&self,
queue_name: &str,
lock_duration_seconds: i32,
) -> Result<Option<crate::types::TypedJob<T>>> {
match self.pop(queue_name, lock_duration_seconds).await? {
Some(job) => {
let payload: T = serde_json::from_value(job.payload)?;
Ok(Some(crate::types::TypedJob {
id: job.id,
queue_name: job.queue_name,
payload,
attempts: job.attempts,
max_attempts: job.max_attempts,
created_at: job.created_at,
}))
}
None => Ok(None),
}
}
}
impl<T: JobQueue + ?Sized> JobQueueExt for T {}
#[async_trait]
pub trait PublisherExt: Publisher {
async fn publish_typed<T: Serialize + Send + Sync>(
&self,
channel: &str,
payload: &T,
) -> Result<()> {
let json = serde_json::to_value(payload)?;
self.publish(channel, &json).await
}
async fn publish_multi_typed<T: Serialize + Send + Sync>(
&self,
channels: &[&str],
payload: &T,
) -> Result<()> {
let json = serde_json::to_value(payload)?;
self.publish_multi(channels, &json).await
}
}
impl<T: Publisher + ?Sized> PublisherExt for T {}