cal_redis/cache/
region.rs

1// File: cal-redis/src/cache/region.rs
2
3use super::CallableCache;
4use crate::local_cache::build_region_identifiers_locally;
5use crate::{get_region_by_ident, get_regions};
6use cal_core::Region;
7use redis::RedisError;
8use std::sync::Arc;
9
10impl CallableCache {
11    /// Retrieves a region by its ID, first checking the local cache and then Redis.
12    ///
13    /// # Arguments
14    /// * `id` - Region ID to look up
15    ///
16    /// # Returns
17    /// * `Result<Option<Region>, RedisError>` - Region if found, None if not found, or a Redis error
18    pub async fn get_region_by_id(self, id: &str) -> Result<Option<Arc<Region>>, RedisError> {
19        println!("CallableCache: get_region_by_id, Getting by ident: {}", id);
20        // Try to get the resolved ID from the local cache
21        if let Some(resolved_id) = self.local_cache.region_idents.get(id) {
22            // If we have a resolved ID, try to get the region from the local cache
23            println!(
24                "CallableCache: get_region_by_id, Got local region_ident: {}",
25                resolved_id
26            );
27            if let Some(region) = self.local_cache.regions.get(resolved_id.as_str()) {
28                println!(
29                    "CallableCache: get_region_by_id, Got local region: {}",
30                    resolved_id
31                );
32                return Ok(Some(region));
33            }
34
35            // If not in local cache, fetch from Redis using the resolved ID
36            match get_region_by_ident(self.remote_cache.connection.clone(), &resolved_id).await? {
37                Some(region) => {
38                    println!(
39                        "CallableCache: get_region_by_id, Got remote Region {}",
40                        region.id
41                    );
42                    // Cache the retrieved region for future use
43                    self.local_cache
44                        .region_idents
45                        .insert(id.to_string(), region.id.to_string());
46                    build_region_identifiers_locally(self.local_cache, Arc::new(region.clone()));
47                    Ok(Some(Arc::new(region)))
48                }
49                None => {
50                    println!(
51                        "CallableCache: get_region_by_id, No remote Region {}",
52                        resolved_id
53                    );
54                    Ok(None)
55                }
56            }
57        } else {
58            // If region identifier not in local cache, try Redis
59            println!(
60                "CallableCache: get_region_by_id, No local region, checking remote {}",
61                id
62            );
63            match get_region_by_ident(self.remote_cache.connection.clone(), id).await? {
64                Some(region) => {
65                    // Cache the retrieved region for future use
66                    println!(
67                        "CallableCache: get_region_by_id, Found remote region {}",
68                        region.id
69                    );
70                    self.local_cache
71                        .region_idents
72                        .insert(id.to_string(), region.id.to_string());
73                    build_region_identifiers_locally(self.local_cache, Arc::new(region.clone()));
74                    Ok(Some(Arc::new(region)))
75                }
76                None => {
77                    println!(
78                        "CallableCache: get_region_by_id, no local or remote region! {}",
79                        id
80                    );
81                    Ok(None)
82                }
83            }
84        }
85    }
86
87    /// Retrieves all regions from Local.
88    ///
89    /// # Returns
90    /// * `Result<Vec<Region>, RedisError>` - Arc Vec of Regions
91    pub async fn get_regions_local(self) -> Result<Arc<Vec<Region>>, RedisError> {
92        println!("[CallableCache::get_regions_local] Getting regions from local cache");
93        // Collect the Arc<Region> values and map them into a Vec<Region> (no cloning of Region data)
94        let regions: Vec<Region> = self
95            .local_cache
96            .regions
97            .iter()
98            .map(|(_, value)| (*value).clone()) // Dereference the Arc and clone the inner Region
99            .collect();
100
101        println!("[CallableCache::get_regions_local] Found {} regions in local cache", regions.len());
102        // Wrap the Vec<Region> in an Arc
103        Ok(Arc::new(regions))
104    }
105
106    /// Retrieves all regions from Redis.
107    ///
108    /// # Returns
109    /// * `Result<Vec<Region>, RedisError>` - Vec of Regions
110    pub async fn get_regions(self) -> Result<Arc<Vec<Region>>, RedisError> {
111        println!("[CallableCache::get_regions] Getting all regions from Redis");
112        let regions = get_regions(self.remote_cache.connection).await?;
113        println!("[CallableCache::get_regions] Retrieved {} regions from Redis", regions.len());
114        for region in &regions {
115            build_region_identifiers_locally(self.local_cache.clone(), Arc::new(region.clone()));
116        }
117        Ok(Arc::new(regions))
118    }
119}