cal-redis 0.1.80

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

use super::CallableCache;
use crate::local_cache::build_region_identifiers_locally;
use crate::{get_region_by_ident, get_regions};
use cal_core::Region;
use redis::RedisError;
use std::sync::Arc;

impl CallableCache {
    /// Retrieves a region by its ID, first checking the local cache and then Redis.
    ///
    /// # Arguments
    /// * `id` - Region ID to look up
    ///
    /// # Returns
    /// * `Result<Option<Region>, RedisError>` - Region if found, None if not found, or a Redis error
    pub async fn get_region_by_id(self, id: &str) -> Result<Option<Arc<Region>>, RedisError> {
        println!("CallableCache: get_region_by_id, Getting by ident: {}", id);
        // Try to get the resolved ID from the local cache
        if let Some(resolved_id) = self.local_cache.region_idents.get(id) {
            // If we have a resolved ID, try to get the region from the local cache
            println!(
                "CallableCache: get_region_by_id, Got local region_ident: {}",
                resolved_id
            );
            if let Some(region) = self.local_cache.regions.get(resolved_id.as_str()) {
                println!(
                    "CallableCache: get_region_by_id, Got local region: {}",
                    resolved_id
                );
                return Ok(Some(region));
            }

            // If not in local cache, fetch from Redis using the resolved ID
            match get_region_by_ident(self.remote_cache.connection.clone(), &resolved_id).await? {
                Some(region) => {
                    println!(
                        "CallableCache: get_region_by_id, Got remote Region {}",
                        region.id
                    );
                    // Cache the retrieved region for future use
                    self.local_cache
                        .region_idents
                        .insert(id.to_string(), region.id.to_string());
                    build_region_identifiers_locally(self.local_cache, Arc::new(region.clone()));
                    Ok(Some(Arc::new(region)))
                }
                None => {
                    println!(
                        "CallableCache: get_region_by_id, No remote Region {}",
                        resolved_id
                    );
                    Ok(None)
                }
            }
        } else {
            // If region identifier not in local cache, try Redis
            println!(
                "CallableCache: get_region_by_id, No local region, checking remote {}",
                id
            );
            match get_region_by_ident(self.remote_cache.connection.clone(), id).await? {
                Some(region) => {
                    // Cache the retrieved region for future use
                    println!(
                        "CallableCache: get_region_by_id, Found remote region {}",
                        region.id
                    );
                    self.local_cache
                        .region_idents
                        .insert(id.to_string(), region.id.to_string());
                    build_region_identifiers_locally(self.local_cache, Arc::new(region.clone()));
                    Ok(Some(Arc::new(region)))
                }
                None => {
                    println!(
                        "CallableCache: get_region_by_id, no local or remote region! {}",
                        id
                    );
                    Ok(None)
                }
            }
        }
    }

    /// Retrieves all regions from Local.
    ///
    /// # Returns
    /// * `Result<Vec<Region>, RedisError>` - Arc Vec of Regions
    pub async fn get_regions_local(self) -> Result<Arc<Vec<Region>>, RedisError> {
        println!("[CallableCache::get_regions_local] Getting regions from local cache");
        // Collect the Arc<Region> values and map them into a Vec<Region> (no cloning of Region data)
        let regions: Vec<Region> = self
            .local_cache
            .regions
            .iter()
            .map(|(_, value)| (*value).clone()) // Dereference the Arc and clone the inner Region
            .collect();

        println!("[CallableCache::get_regions_local] Found {} regions in local cache", regions.len());
        // Wrap the Vec<Region> in an Arc
        Ok(Arc::new(regions))
    }

    /// Retrieves all regions from Redis.
    ///
    /// # Returns
    /// * `Result<Vec<Region>, RedisError>` - Vec of Regions
    pub async fn get_regions(self) -> Result<Arc<Vec<Region>>, RedisError> {
        println!("[CallableCache::get_regions] Getting all regions from Redis");
        let regions = get_regions(self.remote_cache.connection).await?;
        println!("[CallableCache::get_regions] Retrieved {} regions from Redis", regions.len());
        for region in &regions {
            build_region_identifiers_locally(self.local_cache.clone(), Arc::new(region.clone()));
        }
        Ok(Arc::new(regions))
    }
}