use redis::{AsyncCommands, ErrorKind, RedisError, RedisResult, Value};
use redis::aio::MultiplexedConnection;
use serde::de::DeserializeOwned;
use serde::Serialize;
pub fn serialize_to_json<T: Serialize>(item: &T) -> Result<String, RedisError> {
serde_json::to_string(item).map_err(|e| RedisError::from((
ErrorKind::ClientError,
"JSON serialization error",
e.to_string()
)))
}
pub fn deserialize_from_json<T: DeserializeOwned>(json: &str) -> Result<T, RedisError> {
serde_json::from_str(json).map_err(|e| RedisError::from((
ErrorKind::ClientError,
"JSON deserialization error",
e.to_string()
)))
}
pub async fn get_items<T: DeserializeOwned>(
con: MultiplexedConnection,
key: &str
) -> Result<Vec<T>, RedisError> {
let strings: Vec<String> = con.clone().hvals(key).await?;
let mut items = Vec::with_capacity(strings.len());
for json_str in strings {
items.push(deserialize_from_json(&json_str)?);
}
Ok(items)
}
pub async fn get_hash_item<T: DeserializeOwned>(
con: MultiplexedConnection,
key: &str,
field: &str
) -> Result<Option<T>, RedisError> {
match con.clone().hget::<_, _, Option<String>>(key, field).await? {
Some(json_str) => Ok(Some(deserialize_from_json(&json_str)?)),
None => Ok(None),
}
}
pub async fn get_item<T: DeserializeOwned>(
con: MultiplexedConnection,
key: &str,
) -> Result<Option<T>, RedisError> {
match con.clone().get::<_, Option<String>>(key).await? {
Some(json_str) => Ok(Some(deserialize_from_json(&json_str)?)),
None => Ok(None),
}
}
pub async fn insert_items<T, F>(
mut con: MultiplexedConnection,
key: &str,
items: &[T],
id_extractor: F,
) -> RedisResult<Value>
where
T: Serialize,
F: Fn(&T) -> String,
{
let mut entries = Vec::with_capacity(items.len());
for item in items {
let field = id_extractor(item);
let value = serialize_to_json(item)?;
entries.push((field, value));
}
con.hset_multiple(key, &entries).await
}