cal-redis 0.1.80

Callable Redis Implementation
Documentation
// File: cal-redis/src/cache/jambonz.rs

use super::CallableCache;
use crate::common::{deserialize_from_json, serialize_to_json};
use crate::constants::JAMBONZ_KEY;
use cal_core::JambonzEntry;
use redis::{AsyncCommands, RedisError};
use std::sync::Arc;

impl CallableCache {
    /// Inserts a Jambonz entry into Redis.
    ///
    /// # Arguments
    /// * `entry` - The Jambonz entry to insert
    ///
    /// # Returns
    /// * `Result<(), RedisError>` - Ok if successful, or a Redis error
    pub async fn insert_jambonz_entry(&self, entry: JambonzEntry) -> Result<(), RedisError> {
        println!(
            "[CallableCache::insert_jambonz_entry] Inserting Jambonz entry for realm: {}",
            entry.sip_realm
        );

        let mut con = self.redis_connection();
        let value = serialize_to_json(&entry)?;

        // Store in hash with sip_realm as field
        con.hset(JAMBONZ_KEY, &entry.sip_realm, value).await?;

        println!("[CallableCache::insert_jambonz_entry] Successfully inserted Jambonz entry");
        Ok(())
    }

    /// Retrieves a Jambonz entry by SIP realm.
    ///
    /// # Arguments
    /// * `sip_realm` - The SIP realm (e.g., insurancesearch.connect.callable.io)
    ///
    /// # Returns
    /// * `Result<Option<Arc<JambonzEntry>>, RedisError>` - The entry if found, None if not found, or a Redis error
    pub async fn get_jambonz_entry(
        &self,
        sip_realm: &str,
    ) -> Result<Option<Arc<JambonzEntry>>, RedisError> {
        println!(
            "[CallableCache::get_jambonz_entry] Getting Jambonz entry for realm: {}",
            sip_realm
        );

        let con = self.redis_connection();
        let value: Option<String> = con.clone().hget(JAMBONZ_KEY, sip_realm).await?;

        match value {
            Some(json_str) => {
                let entry: JambonzEntry = deserialize_from_json(&json_str)?;
                println!("[CallableCache::get_jambonz_entry] Found Jambonz entry");
                Ok(Some(Arc::new(entry)))
            }
            None => {
                println!("[CallableCache::get_jambonz_entry] Jambonz entry not found");
                Ok(None)
            }
        }
    }

    /// Retrieves all Jambonz entries.
    ///
    /// # Returns
    /// * `Result<Vec<Arc<JambonzEntry>>, RedisError>` - List of all entries
    pub async fn get_all_jambonz_entries(&self) -> Result<Vec<Arc<JambonzEntry>>, RedisError> {
        println!("[CallableCache::get_all_jambonz_entries] Getting all Jambonz entries");

        let con = self.redis_connection();
        let values: Vec<String> = con.clone().hvals(JAMBONZ_KEY).await?;

        let mut entries = Vec::new();
        for json_str in values {
            match deserialize_from_json::<JambonzEntry>(&json_str) {
                Ok(entry) => {
                    entries.push(Arc::new(entry));
                }
                Err(e) => {
                    println!(
                        "[CallableCache::get_all_jambonz_entries] Failed to deserialize entry: {}",
                        e
                    );
                }
            }
        }

        println!(
            "[CallableCache::get_all_jambonz_entries] Found {} total entries",
            entries.len()
        );
        Ok(entries)
    }

    /// Deletes a Jambonz entry from Redis.
    ///
    /// # Arguments
    /// * `sip_realm` - The SIP realm to delete
    ///
    /// # Returns
    /// * `Result<bool, RedisError>` - true if deleted, false if not found
    pub async fn delete_jambonz_entry(
        &self,
        sip_realm: &str,
    ) -> Result<bool, RedisError> {
        println!(
            "[CallableCache::delete_jambonz_entry] Deleting Jambonz entry for realm: {}",
            sip_realm
        );

        let mut con = self.redis_connection();
        let deleted: bool = con.hdel(JAMBONZ_KEY, sip_realm).await?;

        if deleted {
            println!("[CallableCache::delete_jambonz_entry] Successfully deleted Jambonz entry");
        } else {
            println!("[CallableCache::delete_jambonz_entry] Entry not found");
        }

        Ok(deleted)
    }

    /// Batch insert multiple Jambonz entries.
    ///
    /// # Arguments
    /// * `entries` - Vector of Jambonz entries to insert
    ///
    /// # Returns
    /// * `Result<(), RedisError>` - Ok if successful, or a Redis error
    pub async fn insert_jambonz_entries(&self, entries: Vec<JambonzEntry>) -> Result<(), RedisError> {
        println!(
            "[CallableCache::insert_jambonz_entries] Inserting {} Jambonz entries",
            entries.len()
        );

        if entries.is_empty() {
            return Ok(());
        }

        let mut con = self.redis_connection();
        let mut pipe = redis::pipe();

        for entry in entries {
            let value = serialize_to_json(&entry)?;
            pipe.hset(JAMBONZ_KEY, &entry.sip_realm, value);
        }

        pipe.query_async(&mut con).await?;

        println!("[CallableCache::insert_jambonz_entries] Successfully inserted all entries");
        Ok(())
    }
}