cal_redis/
common.rs

1// File: cal-redis/src/common.rs
2
3use redis::{AsyncCommands, ErrorKind, RedisError, RedisResult, Value};
4use redis::aio::MultiplexedConnection;
5use serde::de::DeserializeOwned;
6use serde::Serialize;
7
8/// Serializes an item to a JSON string with proper error handling.
9pub fn serialize_to_json<T: Serialize>(item: &T) -> Result<String, RedisError> {
10    serde_json::to_string(item).map_err(|e| RedisError::from((
11        ErrorKind::ClientError,
12        "JSON serialization error",
13        e.to_string()
14    )))
15}
16
17/// Deserializes a JSON string into the specified type with proper error handling.
18pub fn deserialize_from_json<T: DeserializeOwned>(json: &str) -> Result<T, RedisError> {
19    serde_json::from_str(json).map_err(|e| RedisError::from((
20        ErrorKind::ClientError,
21        "JSON deserialization error",
22        e.to_string()
23    )))
24}
25
26/// Retrieves all values from a Redis hash and deserializes them into the specified type.
27pub async fn get_items<T: DeserializeOwned>(
28    con: MultiplexedConnection,
29    key: &str
30) -> Result<Vec<T>, RedisError> {
31    let strings: Vec<String> = con.clone().hvals(key).await?;
32
33    let mut items = Vec::with_capacity(strings.len());
34    for json_str in strings {
35        items.push(deserialize_from_json(&json_str)?);
36    }
37
38    Ok(items)
39}
40
41/// Retrieves a single value from a Redis hash and deserializes it into the specified type.
42pub async fn get_hash_item<T: DeserializeOwned>(
43    con: MultiplexedConnection,
44    key: &str,
45    field: &str
46) -> Result<Option<T>, RedisError> {
47    match con.clone().hget::<_, _, Option<String>>(key, field).await? {
48        Some(json_str) => Ok(Some(deserialize_from_json(&json_str)?)),
49        None => Ok(None),
50    }
51}
52
53/// Retrieves a single value from a Redis key and deserializes it into the specified type.
54pub async fn get_item<T: DeserializeOwned>(
55    con: MultiplexedConnection,
56    key: &str,
57) -> Result<Option<T>, RedisError> {
58    match con.clone().get::<_, Option<String>>(key).await? {
59        Some(json_str) => Ok(Some(deserialize_from_json(&json_str)?)),
60        None => Ok(None),
61    }
62}
63
64/// Inserts multiple items into a Redis hash, serializing each item to JSON.
65pub async fn insert_items<T, F>(
66    mut con: MultiplexedConnection,
67    key: &str,
68    items: &[T],
69    id_extractor: F,
70) -> RedisResult<Value>
71where
72    T: Serialize,
73    F: Fn(&T) -> String,
74{
75    let mut entries = Vec::with_capacity(items.len());
76
77    for item in items {
78        let field = id_extractor(item);
79        let value = serialize_to_json(item)?;
80        entries.push((field, value));
81    }
82
83    con.hset_multiple(key, &entries).await
84}